MegaGlest/source/glest_game/world/unit_updater.cpp
Mike Hoffert 68455a819f Added setting to disable going into negatives
After all, how does one loot what the other faction does not have? Still,
could be useful for some places, by forcing the opponent to go into
"debt".
2014-07-19 16:38:33 -06:00

3312 lines
141 KiB
C++

// ==============================================================
// This file is part of Glest (www.glest.org)
//
// Copyright (C) 2001-2008 Martiño Figueroa
//
// You can redistribute this code and/or modify it under
// the terms of the GNU General Public License as published
// by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version
// ==============================================================
#include "unit_updater.h"
#include <algorithm>
#include <cassert>
#include "core_data.h"
#include "config.h"
#include "game.h"
#include "faction.h"
#include "network_manager.h"
#include "object.h"
#include "particle_type.h"
#include "path_finder.h"
#include "renderer.h"
#include "sound.h"
#include "sound_renderer.h"
#include "upgrade.h"
#include "unit.h"
#include "leak_dumper.h"
using namespace Shared::Graphics;
using namespace Shared::Util;
namespace Glest{ namespace Game{
// =====================================================
// class UnitUpdater
// =====================================================
// ===================== PUBLIC ========================
UnitUpdater::UnitUpdater() : mutexAttackWarnings(new Mutex(CODE_AT_LINE)),
mutexUnitRangeCellsLookupItemCache(new Mutex(CODE_AT_LINE)) {
this->game= NULL;
this->gui= NULL;
this->gameCamera= NULL;
this->world= NULL;
this->map= NULL;
this->console= NULL;
this->scriptManager= NULL;
this->pathFinder = NULL;
//UnitRangeCellsLookupItemCacheTimerCount = 0;
attackWarnRange=0;
}
void UnitUpdater::init(Game *game){
this->game= game;
this->gui= game->getGuiPtr();
this->gameCamera= game->getGameCamera();
this->world= game->getWorld();
this->map= world->getMap();
this->console= game->getConsole();
this->scriptManager= game->getScriptManager();
this->pathFinder = NULL;
attackWarnRange=Config::getInstance().getFloat("AttackWarnRange","50.0");
//UnitRangeCellsLookupItemCacheTimerCount = 0;
switch(this->game->getGameSettings()->getPathFinderType()) {
case pfBasic:
pathFinder = new PathFinder();
pathFinder->init(map);
break;
default:
throw megaglest_runtime_error("detected unsupported pathfinder type!");
}
}
void UnitUpdater::clearUnitPrecache(Unit *unit) {
if(pathFinder != NULL) {
pathFinder->clearUnitPrecache(unit);
}
}
void UnitUpdater::removeUnitPrecache(Unit *unit) {
if(pathFinder != NULL) {
pathFinder->removeUnitPrecache(unit);
}
}
UnitUpdater::~UnitUpdater() {
//UnitRangeCellsLookupItemCache.clear();
delete pathFinder;
pathFinder = NULL;
MutexSafeWrapper safeMutex(mutexAttackWarnings,string(__FILE__) + "_" + intToStr(__LINE__));
while(attackWarnings.empty() == false) {
AttackWarningData* awd = attackWarnings.back();
attackWarnings.pop_back();
delete awd;
}
safeMutex.ReleaseLock();
delete mutexAttackWarnings;
mutexAttackWarnings = NULL;
delete mutexUnitRangeCellsLookupItemCache;
mutexUnitRangeCellsLookupItemCache = NULL;
}
// ==================== progress skills ====================
//skill dependent actions
bool UnitUpdater::updateUnit(Unit *unit) {
bool processUnitCommand = false;
Chrono chrono;
if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled) chrono.start();
if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s] Line: %d took msecs: %lld --------------------------- [START OF METHOD] ---------------------------\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis());
SoundRenderer &soundRenderer= SoundRenderer::getInstance();
//play skill sound
const SkillType *currSkill= unit->getCurrSkill();
if(currSkill->getSound() != NULL) {
float soundStartTime= currSkill->getSoundStartTime();
if(soundStartTime >= unit->getLastAnimProgressAsFloat() && soundStartTime < unit->getAnimProgressAsFloat()) {
if(map->getSurfaceCell(Map::toSurfCoords(unit->getPos()))->isVisible(world->getThisTeamIndex()) ||
(game->getWorld()->showWorldForPlayer(game->getWorld()->getThisTeamIndex()) == true)) {
soundRenderer.playFx(currSkill->getSound(), unit->getCurrVector(), gameCamera->getPos());
}
}
}
if (currSkill->getShake()) {
float shakeStartTime = currSkill->getShakeStartTime();
if (shakeStartTime >= unit->getLastAnimProgressAsFloat()
&& shakeStartTime < unit->getAnimProgressAsFloat()) {
bool visibleAffected=false;
bool cameraViewAffected=false;
bool cameraDistanceAffected=false;
bool enabled=false;
if (game->getWorld()->getThisFactionIndex() == unit->getFactionIndex()) {
visibleAffected=currSkill->getShakeSelfVisible();
cameraViewAffected=currSkill->getShakeSelfInCameraView();
cameraDistanceAffected=currSkill->getShakeSelfCameraAffected();
enabled=currSkill->getShakeSelfEnabled();
} else if (unit->getTeam() == world->getThisTeamIndex()) {
visibleAffected=currSkill->getShakeTeamVisible();
cameraViewAffected=currSkill->getShakeTeamInCameraView();
cameraDistanceAffected=currSkill->getShakeTeamCameraAffected();
enabled=currSkill->getShakeTeamEnabled();
} else {
visibleAffected=currSkill->getShakeEnemyVisible();
cameraViewAffected=currSkill->getShakeEnemyInCameraView();
cameraDistanceAffected=currSkill->getShakeEnemyCameraAffected();
enabled=currSkill->getShakeEnemyEnabled();
}
bool visibility=(!visibleAffected)||(map->getSurfaceCell(Map::toSurfCoords(unit->getPos()))->isVisible(world->getThisTeamIndex()) ||
(game->getWorld()->showWorldForPlayer(game->getWorld()->getThisTeamIndex()) == true));
bool cameraAffected=(!cameraViewAffected) || unit->getVisible();
if(visibility && cameraAffected && enabled) {
game->getGameCameraPtr()->shake( currSkill->getShakeDuration(), currSkill->getShakeIntensity(),cameraDistanceAffected,unit->getCurrVector());
}
}
}
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());
unit->updateTimedParticles();
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() == scAttack) {
const AttackSkillType *ast= static_cast<const AttackSkillType*>(unit->getCurrSkill());
float attackStartTime = truncateDecimal<float>(ast->getAttackStartTime(),6);
float lastAnimProgress = truncateDecimal<float>(unit->getLastAnimProgressAsFloat(),6);
float animProgress = truncateDecimal<float>(unit->getAnimProgressAsFloat(),6);
bool startAttackParticleSystemNow = (attackStartTime >= lastAnimProgress && attackStartTime < animProgress);
char szBuf[8096]="";
snprintf(szBuf,8095,"attackStartTime = %f, lastAnimProgress = %f, animProgress = %f startAttackParticleSystemNow = %d",attackStartTime,lastAnimProgress,animProgress,startAttackParticleSystemNow);
unit->setNetworkCRCParticleLogInfo(szBuf);
if(startAttackParticleSystemNow == true) {
startAttackParticleSystem(unit);
}
}
if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s] Line: %d took msecs: %lld [after attack particle system]\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis());
bool update = unit->update();
if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s] Line: %d took msecs: %lld [after unit->update()]\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis());
//printf("Update Unit [%d - %s] = %d\n",unit->getId(),unit->getType()->getName().c_str(),update);
//update unit
if(update == true) {
//SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
processUnitCommand = true;
updateUnitCommand(unit,-1);
if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s] Line: %d took msecs: %lld [after updateUnitCommand()]\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis());
//if unit is out of EP, it stops
if(unit->computeEp() == true) {
bool reQueueHoldPosition = false;
string holdPositionName = "";
if(unit->getCurrCommand() != NULL &&
unit->getCurrCommand()->getCommandType()->getClass() == ccAttackStopped) {
reQueueHoldPosition = true;
holdPositionName = unit->getCurrCommand()->getCommandType()->getName(false);
}
unit->setCurrSkill(scStop);
unit->cancelCommand();
if(reQueueHoldPosition == true) {
//Search for a command that can produce the unit
const UnitType *ut = unit->getType();
for(int i= 0; i < ut->getCommandTypeCount(); ++i) {
const CommandType* ct= ut->getCommandType(i);
if(ct != NULL && ct->getClass() == ccAttackStopped) {
const AttackStoppedCommandType *act= static_cast<const AttackStoppedCommandType*>(ct);
if(act != NULL && act->getName(false) == holdPositionName) {
if(SystemFlags::getSystemSettingType(SystemFlags::debugUnitCommands).enabled) SystemFlags::OutputDebug(SystemFlags::debugUnitCommands,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
//printf("Re-Queing hold pos = %d, ep = %d skillep = %d skillname [%s]\n ",unit->getFaction()->reqsOk(act),unit->getEp(),act->getAttackSkillType()->getEpCost(),act->getName().c_str());
if(unit->getFaction()->reqsOk(act) == true &&
unit->getEp() >= act->getStopSkillType()->getEpCost()) {
unit->giveCommand(new Command(act),true);
}
if(SystemFlags::getSystemSettingType(SystemFlags::debugUnitCommands).enabled) SystemFlags::OutputDebug(SystemFlags::debugUnitCommands,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
break;
}
}
}
}
}
if(unit->getCurrSkill() != NULL && unit->getCurrSkill()->getClass() != scAttack) {
// !!! Is this causing choppy network play somehow?
//unit->computeHp();
}
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());
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());
}
}
}
}
}
//move unit in cells
if(unit->getCurrSkill()->getClass() == scMove) {
world->moveUnitCells(unit);
if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s] Line: %d took msecs: %lld [after world->moveUnitCells()]\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis());
//play water sound
if(map->getCell(unit->getPos())->getHeight() < map->getWaterLevel() && unit->getCurrField() == fLand) {
if(Config::getInstance().getBool("DisableWaterSounds","false") == false) {
soundRenderer.playFx(
CoreData::getInstance().getWaterSound(),
unit->getCurrVector(),
gameCamera->getPos()
);
if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s] Line: %d took msecs: %lld [after soundFx()]\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis());
}
}
}
}
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());
//unit death
if(unit->isDead() && unit->getCurrSkill()->getClass() != scDie) {
unit->kill();
}
if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s] Line: %d took msecs: %lld --------------------------- [END OF METHOD] ---------------------------\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis());
return processUnitCommand;
}
// ==================== progress commands ====================
//VERY IMPORTANT: compute next state depending on the first order of the list
void UnitUpdater::updateUnitCommand(Unit *unit, int frameIndex) {
try {
bool minorDebugPerformance = false;
Chrono chrono;
if((minorDebugPerformance == true && frameIndex > 0) || SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled) chrono.start();
//if unit has command process it
bool hasCommand = (unit->anyCommand());
if((minorDebugPerformance && frameIndex > 0) && chrono.getMillis() >= 1) printf("UnitUpdate [%d - %s] #1-unit threaded updates on frame: %d took [%lld] msecs\n",unit->getId(),unit->getType()->getName(false).c_str(),frameIndex,(long long int)chrono.getMillis());
int64 elapsed1 = 0;
if(minorDebugPerformance && frameIndex > 0) elapsed1 = chrono.getMillis();
if(hasCommand == true) {
if(SystemFlags::getSystemSettingType(SystemFlags::debugUnitCommands).enabled) SystemFlags::OutputDebug(SystemFlags::debugUnitCommands,"In [%s::%s Line: %d] unit [%s] has command [%s]\n",__FILE__,__FUNCTION__,__LINE__,unit->toString(false).c_str(), unit->getCurrCommand()->toString(false).c_str());
bool commandUsesPathFinder = (frameIndex < 0);
if(frameIndex > 0) {
if(unit->getCurrCommand() != NULL && unit->getCurrCommand()->getCommandType() != NULL) {
commandUsesPathFinder = unit->getCurrCommand()->getCommandType()->usesPathfinder();
// Clear previous cached unit data
if(commandUsesPathFinder == true) {
clearUnitPrecache(unit);
}
}
}
if(commandUsesPathFinder == true) {
if(unit->getCurrCommand() != NULL && unit->getCurrCommand()->getCommandType() != NULL) {
unit->getCurrCommand()->getCommandType()->update(this, unit, frameIndex);
}
}
if((minorDebugPerformance && frameIndex > 0) && (chrono.getMillis() - elapsed1) >= 1) {
//CommandClass cc = unit->getCurrCommand()->getCommandType()->commandTypeClass;
printf("UnitUpdate [%d - %s] #2-unit threaded updates on frame: %d commandUsesPathFinder = %d took [%lld] msecs\nCommand: %s\n",unit->getId(),unit->getType()->getName(false).c_str(),frameIndex,commandUsesPathFinder,(long long int)chrono.getMillis() - elapsed1,unit->getCurrCommand()->toString(false).c_str());
}
}
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());
if(frameIndex < 0) {
//if no commands stop and add stop command
if(unit->anyCommand() == false && unit->isOperative()) {
if(SystemFlags::getSystemSettingType(SystemFlags::debugUnitCommands).enabled) SystemFlags::OutputDebug(SystemFlags::debugUnitCommands,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
if(unit->getType()->hasSkillClass(scStop)) {
unit->setCurrSkill(scStop);
}
if(unit->getType()->hasCommandClass(ccStop)) {
unit->giveCommand(new Command(unit->getType()->getFirstCtOfClass(ccStop)));
}
}
}
if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s] Line: %d took msecs: %lld --------------------------- [END OF METHOD] ---------------------------\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis());
if((minorDebugPerformance && frameIndex > 0) && chrono.getMillis() >= 1) printf("UnitUpdate [%d - %s] #3-unit threaded updates on frame: %d took [%lld] msecs\n",unit->getId(),unit->getType()->getName(false).c_str(),frameIndex,(long long int)chrono.getMillis());
}
catch(const exception &ex) {
//setRunningStatus(false);
SystemFlags::OutputDebug(SystemFlags::debugError,"In [%s::%s Line: %d] Error [%s]\n",__FILE__,__FUNCTION__,__LINE__,ex.what());
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
throw megaglest_runtime_error(ex.what());
}
catch(...) {
char szBuf[8096]="";
snprintf(szBuf,8096,"In [%s::%s %d] UNKNOWN error\n",__FILE__,__FUNCTION__,__LINE__);
SystemFlags::OutputDebug(SystemFlags::debugError,szBuf);
throw megaglest_runtime_error(szBuf);
}
}
// ==================== updateStop ====================
void UnitUpdater::updateStop(Unit *unit, int frameIndex) {
try {
// Nothing to do
if(frameIndex >= 0) {
clearUnitPrecache(unit);
return;
}
Chrono chrono;
if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled) chrono.start();
Command *command= unit->getCurrCommand();
if(command == NULL) {
throw megaglest_runtime_error("command == NULL");
}
const StopCommandType *sct = static_cast<const StopCommandType*>(command->getCommandType());
Unit *sighted=NULL;
unit->setCurrSkill(sct->getStopSkillType());
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());
//we can attack any unit => attack it
if(unit->getType()->hasSkillClass(scAttack)) {
int cmdTypeCount = unit->getType()->getCommandTypeCount();
for(int i = 0; i < cmdTypeCount; ++i) {
const CommandType *ct= unit->getType()->getCommandType(i);
//look for an attack skill
const AttackSkillType *ast= NULL;
if(ct->getClass() == ccAttack) {
ast= static_cast<const AttackCommandType*>(ct)->getAttackSkillType();
}
else if(ct->getClass() == ccAttackStopped) {
ast= static_cast<const AttackStoppedCommandType*>(ct)->getAttackSkillType();
}
//use it to attack
if(ast != NULL) {
if(attackableOnSight(unit, &sighted, ast, (frameIndex >= 0))) {
//SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
unit->giveCommand(new Command(ct, sighted->getPos()));
break;
}
}
}
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());
}
//see any unit and cant attack it => run
else if(unit->getType()->hasCommandClass(ccMove)) {
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());
if(attackerOnSight(unit, &sighted, (frameIndex >= 0))) {
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());
Vec2i escapePos = unit->getPos() * 2 - sighted->getPos();
//SystemFlags::OutputDebug(SystemFlags::debugUnitCommands,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
unit->giveCommand(new Command(unit->getType()->getFirstCtOfClass(ccMove), escapePos));
}
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());
}
if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s] Line: %d took msecs: %lld --------------------------- [END OF METHOD] ---------------------------\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis());
}
catch(const exception &ex) {
//setRunningStatus(false);
SystemFlags::OutputDebug(SystemFlags::debugError,"In [%s::%s Line: %d] Error [%s]\n",__FILE__,__FUNCTION__,__LINE__,ex.what());
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
throw megaglest_runtime_error(ex.what());
}
catch(...) {
char szBuf[8096]="";
snprintf(szBuf,8096,"In [%s::%s %d] UNKNOWN error\n",__FILE__,__FUNCTION__,__LINE__);
SystemFlags::OutputDebug(SystemFlags::debugError,szBuf);
throw megaglest_runtime_error(szBuf);
}
}
// ==================== updateMove ====================
void UnitUpdater::updateMove(Unit *unit, int frameIndex) {
try {
Chrono chrono;
if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled) chrono.start();
Command *command= unit->getCurrCommand();
if(command == NULL) {
throw megaglest_runtime_error("command == NULL");
}
const MoveCommandType *mct= static_cast<const MoveCommandType*>(command->getCommandType());
Vec2i pos= command->getUnit()!=NULL? command->getUnit()->getCenteredPos(): command->getPos();
if(SystemFlags::getSystemSettingType(SystemFlags::debugWorldSynch).enabled == true && frameIndex < 0) {
char szBuf[8096]="";
snprintf(szBuf,8096,"[updateMove] pos [%s] unit [%d - %s] cmd [%s]",pos.getString().c_str(),unit->getId(),unit->getFullName(false).c_str(),command->toString(false).c_str());
unit->logSynchData(__FILE__,__LINE__,szBuf);
}
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());
TravelState tsValue = tsImpossible;
switch(this->game->getGameSettings()->getPathFinderType()) {
case pfBasic:
tsValue = pathFinder->findPath(unit, pos, NULL, frameIndex);
break;
default:
throw megaglest_runtime_error("detected unsupported pathfinder type!");
}
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());
if(frameIndex < 0) {
switch (tsValue) {
case tsMoving:
unit->setCurrSkill(mct->getMoveSkillType());
break;
case tsBlocked:
unit->setCurrSkill(scStop);
if(unit->getPath()->isBlocked()){
unit->finishCommand();
}
break;
default:
unit->finishCommand();
break;
}
}
if(SystemFlags::getSystemSettingType(SystemFlags::debugWorldSynch).enabled == true && frameIndex < 0) {
char szBuf[8096]="";
snprintf(szBuf,8096,"[updateMove] tsValue [%d]",tsValue);
unit->logSynchData(extractFileFromDirectoryPath(__FILE__).c_str(),__LINE__,szBuf);
}
if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s] Line: %d took msecs: %lld --------------------------- [END OF METHOD] ---------------------------\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis());
}
catch(const exception &ex) {
//setRunningStatus(false);
SystemFlags::OutputDebug(SystemFlags::debugError,"In [%s::%s Line: %d] Error [%s]\n",__FILE__,__FUNCTION__,__LINE__,ex.what());
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
throw megaglest_runtime_error(ex.what());
}
catch(...) {
char szBuf[8096]="";
snprintf(szBuf,8096,"In [%s::%s %d] UNKNOWN error\n",__FILE__,__FUNCTION__,__LINE__);
SystemFlags::OutputDebug(SystemFlags::debugError,szBuf);
throw megaglest_runtime_error(szBuf);
}
}
// ==================== updateAttack ====================
void UnitUpdater::updateAttack(Unit *unit, int frameIndex) {
try {
if(SystemFlags::getSystemSettingType(SystemFlags::debugWorldSynch).enabled == true && frameIndex < 0) {
char szBuf[8096]="";
snprintf(szBuf,8096,"[updateAttack]");
unit->logSynchData(extractFileFromDirectoryPath(__FILE__).c_str(),__LINE__,szBuf);
}
Chrono chrono;
if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled) chrono.start();
Command *command= unit->getCurrCommand();
if(command == NULL) {
if(SystemFlags::getSystemSettingType(SystemFlags::debugWorldSynch).enabled == true && frameIndex < 0) {
char szBuf[8096]="";
snprintf(szBuf,8096,"[updateAttack]");
unit->logSynchData(extractFileFromDirectoryPath(__FILE__).c_str(),__LINE__,szBuf);
}
return;
}
const AttackCommandType *act= static_cast<const AttackCommandType*>(command->getCommandType());
if(act == NULL) {
if(SystemFlags::getSystemSettingType(SystemFlags::debugWorldSynch).enabled == true && frameIndex < 0) {
char szBuf[8096]="";
snprintf(szBuf,8096,"[updateAttack]");
unit->logSynchData(extractFileFromDirectoryPath(__FILE__).c_str(),__LINE__,szBuf);
}
return;
}
Unit *target= NULL;
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());
if( (command->getUnit() == NULL || !(command->getUnit()->isAlive()) ) && unit->getCommandSize() > 1) {
if(frameIndex < 0) {
unit->finishCommand(); // all queued "ground attacks" are skipped if somthing else is queued after them.
if(SystemFlags::getSystemSettingType(SystemFlags::debugWorldSynch).enabled == true && frameIndex < 0) {
char szBuf[8096]="";
snprintf(szBuf,8096,"[updateAttack]");
unit->logSynchData(extractFileFromDirectoryPath(__FILE__).c_str(),__LINE__,szBuf);
}
}
return;
}
//if found
//if(frameIndex < 0) {
{
if(attackableOnRange(unit, &target, act->getAttackSkillType(),(frameIndex >= 0))) {
if(frameIndex < 0) {
if(unit->getEp() >= act->getAttackSkillType()->getEpCost()) {
unit->setCurrSkill(act->getAttackSkillType());
unit->setTarget(target);
}
else {
unit->setCurrSkill(scStop);
}
if(SystemFlags::getSystemSettingType(SystemFlags::debugWorldSynch).enabled == true && frameIndex < 0) {
char szBuf[8096]="";
snprintf(szBuf,8096,"[updateAttack]");
unit->logSynchData(extractFileFromDirectoryPath(__FILE__).c_str(),__LINE__,szBuf);
}
}
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());
}
else {
//compute target pos
Vec2i pos;
if(command->getUnit() != NULL) {
pos= command->getUnit()->getCenteredPos();
}
else if(attackableOnSight(unit, &target, act->getAttackSkillType(), (frameIndex >= 0))) {
pos= target->getPos();
}
else {
pos= command->getPos();
}
if(SystemFlags::getSystemSettingType(SystemFlags::debugWorldSynch).enabled == true && frameIndex < 0) {
char szBuf[8096]="";
snprintf(szBuf,8096,"[updateAttack] pos [%s] unit->getPos() [%s]",pos.getString().c_str(),unit->getPos().getString().c_str());
unit->logSynchData(__FILE__,__LINE__,szBuf);
}
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());
TravelState tsValue = tsImpossible;
//if(frameIndex < 0) {
{
//printf("In [%s::%s Line: %d] START pathfind for attacker [%d - %s]\n",__FILE__,__FUNCTION__,__LINE__,unit->getId(), unit->getType()->getName().c_str());
//fflush(stdout);
switch(this->game->getGameSettings()->getPathFinderType()) {
case pfBasic:
tsValue = pathFinder->findPath(unit, pos, NULL, frameIndex);
break;
default:
throw megaglest_runtime_error("detected unsupported pathfinder type!");
}
//printf("In [%s::%s Line: %d] END pathfind for attacker [%d - %s]\n",__FILE__,__FUNCTION__,__LINE__,unit->getId(), unit->getType()->getName().c_str());
//fflush(stdout);
}
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());
if(frameIndex < 0) {
if(command->getUnit() != NULL && !command->getUnit()->isAlive() && unit->getCommandSize() > 1) {
// don't run over to dead body if there is still something to do in the queue
unit->finishCommand();
if(SystemFlags::getSystemSettingType(SystemFlags::debugWorldSynch).enabled == true && frameIndex < 0) {
char szBuf[8096]="";
snprintf(szBuf,8096,"[updateAttack]");
unit->logSynchData(extractFileFromDirectoryPath(__FILE__).c_str(),__LINE__,szBuf);
}
}
else {
//if unit arrives destPos order has ended
switch (tsValue) {
case tsMoving:
unit->setCurrSkill(act->getMoveSkillType());
break;
case tsBlocked:
if(unit->getPath()->isBlocked()) {
unit->finishCommand();
}
break;
default:
unit->finishCommand();
break;
}
/*
case tsMoving:
unit->setCurrSkill(act->getMoveSkillType());
{
std::pair<bool,Unit *> beingAttacked = unitBeingAttacked(unit);
if(beingAttacked.first == true) {
Unit *enemy = beingAttacked.second;
const AttackCommandType *act_forenemy = unit->getType()->getFirstAttackCommand(enemy->getCurrField());
if(act_forenemy != NULL) {
if(unit->getEp() >= act_forenemy->getAttackSkillType()->getEpCost()) {
unit->setCurrSkill(act_forenemy->getAttackSkillType());
unit->setTarget(enemy);
}
//aiInterface->giveCommand(i, act_forenemy, beingAttacked.second->getPos());
}
else {
const AttackStoppedCommandType *asct_forenemy = unit->getType()->getFirstAttackStoppedCommand(enemy->getCurrField());
if(asct_forenemy != NULL) {
//aiInterface->giveCommand(i, asct_forenemy, beingAttacked.second->getCenteredPos());
if(unit->getEp() >= asct_forenemy->getAttackSkillType()->getEpCost()) {
unit->setCurrSkill(asct_forenemy->getAttackSkillType());
unit->setTarget(enemy);
}
}
}
}
}
break;
case tsBlocked:
if(unit->getPath()->isBlocked()){
unit->finishCommand();
}
break;
default:
unit->finishCommand();
}
*/
if(SystemFlags::getSystemSettingType(SystemFlags::debugWorldSynch).enabled == true && frameIndex < 0) {
char szBuf[8096]="";
snprintf(szBuf,8096,"[updateAttack]");
unit->logSynchData(extractFileFromDirectoryPath(__FILE__).c_str(),__LINE__,szBuf);
}
}
}
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());
}
}
if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s] Line: %d took msecs: %lld --------------------------- [END OF METHOD] ---------------------------\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis());
}
catch(const exception &ex) {
//setRunningStatus(false);
SystemFlags::OutputDebug(SystemFlags::debugError,"In [%s::%s Line: %d] Loc [%s]\n",__FILE__,__FUNCTION__,__LINE__,ex.what());
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
throw megaglest_runtime_error(ex.what());
}
catch(...) {
char szBuf[8096]="";
snprintf(szBuf,8096,"In [%s::%s %d] UNKNOWN error\n",__FILE__,__FUNCTION__,__LINE__);
SystemFlags::OutputDebug(SystemFlags::debugError,szBuf);
throw megaglest_runtime_error(szBuf);
}
}
// ==================== updateAttackStopped ====================
void UnitUpdater::updateAttackStopped(Unit *unit, int frameIndex) {
try {
// Nothing to do
if(frameIndex >= 0) {
if(SystemFlags::getSystemSettingType(SystemFlags::debugWorldSynch).enabled == true && frameIndex >= 0) {
char szBuf[8096]="";
snprintf(szBuf,8096,"[updateAttackStopped]");
unit->logSynchDataThreaded(extractFileFromDirectoryPath(__FILE__).c_str(),__LINE__,szBuf);
}
clearUnitPrecache(unit);
return;
}
Chrono chrono;
if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled) chrono.start();
Command *command= unit->getCurrCommand();
if(command == NULL) {
throw megaglest_runtime_error("command == NULL");
}
const AttackStoppedCommandType *asct= static_cast<const AttackStoppedCommandType*>(command->getCommandType());
Unit *enemy=NULL;
if(unit->getCommandSize() > 1) {
if(SystemFlags::getSystemSettingType(SystemFlags::debugWorldSynch).enabled == true && frameIndex < 0) {
char szBuf[8096]="";
snprintf(szBuf,8096,"[updateAttackStopped]");
unit->logSynchData(extractFileFromDirectoryPath(__FILE__).c_str(),__LINE__,szBuf);
}
unit->finishCommand(); // attackStopped is skipped if somthing else is queued after this.
return;
}
float distToUnit=-1;
std::pair<bool,Unit *> result = make_pair(false,(Unit *)NULL);
unitBeingAttacked(result, unit, asct->getAttackSkillType(), &distToUnit);
if(result.first == true) {
unit->setCurrSkill(asct->getAttackSkillType());
unit->setTarget(result.second);
if(SystemFlags::getSystemSettingType(SystemFlags::debugWorldSynch).enabled == true && frameIndex < 0) {
char szBuf[8096]="";
snprintf(szBuf,8096,"[updateAttackStopped]");
unit->logSynchData(extractFileFromDirectoryPath(__FILE__).c_str(),__LINE__,szBuf);
}
}
else if(attackableOnRange(unit, &enemy, asct->getAttackSkillType(),(frameIndex >= 0))) {
unit->setCurrSkill(asct->getAttackSkillType());
unit->setTarget(enemy);
if(SystemFlags::getSystemSettingType(SystemFlags::debugWorldSynch).enabled == true && frameIndex < 0) {
char szBuf[8096]="";
snprintf(szBuf,8096,"[updateAttackStopped]");
unit->logSynchData(extractFileFromDirectoryPath(__FILE__).c_str(),__LINE__,szBuf);
}
}
else {
unit->setCurrSkill(asct->getStopSkillType());
if(SystemFlags::getSystemSettingType(SystemFlags::debugWorldSynch).enabled == true && frameIndex < 0) {
char szBuf[8096]="";
snprintf(szBuf,8096,"[updateAttackStopped]");
unit->logSynchData(extractFileFromDirectoryPath(__FILE__).c_str(),__LINE__,szBuf);
}
}
if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s] Line: %d took msecs: %lld --------------------------- [END OF METHOD] ---------------------------\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis());
}
catch(const exception &ex) {
//setRunningStatus(false);
SystemFlags::OutputDebug(SystemFlags::debugError,"In [%s::%s Line: %d] Error [%s]\n",__FILE__,__FUNCTION__,__LINE__,ex.what());
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
throw megaglest_runtime_error(ex.what());
}
catch(...) {
char szBuf[8096]="";
snprintf(szBuf,8096,"In [%s::%s %d] UNKNOWN error\n",__FILE__,__FUNCTION__,__LINE__);
SystemFlags::OutputDebug(SystemFlags::debugError,szBuf);
throw megaglest_runtime_error(szBuf);
}
}
void UnitUpdater::unitBeingAttacked(std::pair<bool,Unit *> &result, const Unit *unit, const AttackSkillType *ast, float *currentDistToUnit) {
//std::pair<bool,Unit *> result = make_pair(false,(Unit *)NULL);
float distToUnit = -1;
if(currentDistToUnit != NULL) {
distToUnit = *currentDistToUnit;
}
if(ast != NULL) {
vector<Unit*> enemies = enemyUnitsOnRange(unit,ast);
for(unsigned j = 0; j < enemies.size(); ++j) {
Unit *enemy = enemies[j];
//printf("~~~~~~~~ Unit [%s - %d] enemy # %d found enemy [%s - %d] distToUnit = %f\n",unit->getFullName().c_str(),unit->getId(),j,enemy->getFullName().c_str(),enemy->getId(),unit->getCenteredPos().dist(enemy->getCenteredPos()));
if(distToUnit < 0 || unit->getCenteredPos().dist(enemy->getCenteredPos()) < distToUnit) {
distToUnit = unit->getCenteredPos().dist(enemy->getCenteredPos());
if(ast->getAttackRange() >= distToUnit){
result.first= true;
result.second= enemy;
break;
}
}
}
}
if(currentDistToUnit != NULL) {
*currentDistToUnit = distToUnit;
}
// if(result.first == true) {
// printf("~~~~~~~~ Unit [%s - %d] found enemy [%s - %d] distToUnit = %f\n",unit->getFullName().c_str(),unit->getId(),result.second->getFullName().c_str(),result.second->getId(),distToUnit);
// }
//return result;
}
std::pair<bool,Unit *> UnitUpdater::unitBeingAttacked(const Unit *unit) {
std::pair<bool,Unit *> result = make_pair(false,(Unit *)NULL);
float distToUnit = -1;
for(unsigned int i = 0; i < (unsigned int)unit->getType()->getSkillTypeCount(); ++i) {
const SkillType *st = unit->getType()->getSkillType(i);
const AttackSkillType *ast = dynamic_cast<const AttackSkillType *>(st);
unitBeingAttacked(result, unit, ast, &distToUnit);
}
// if(result.first == true) {
// printf("~~~~~~~~ Unit [%s - %d] found enemy [%s - %d] distToUnit = %f\n",unit->getFullName().c_str(),unit->getId(),result.second->getFullName().c_str(),result.second->getId(),distToUnit);
// }
return result;
}
// ==================== updateBuild ====================
void UnitUpdater::updateBuild(Unit *unit, int frameIndex) {
try {
if(SystemFlags::getSystemSettingType(SystemFlags::debugWorldSynch).enabled == true && frameIndex < 0) {
char szBuf[8096]="";
snprintf(szBuf,8096,"[updateBuild]");
unit->logSynchData(extractFileFromDirectoryPath(__FILE__).c_str(),__LINE__,szBuf);
}
Chrono chrono;
if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled) chrono.start();
if(SystemFlags::getSystemSettingType(SystemFlags::debugUnitCommands).enabled) SystemFlags::OutputDebug(SystemFlags::debugUnitCommands,"In [%s::%s Line: %d] unit [%s] will build using command [%s]\n",__FILE__,__FUNCTION__,__LINE__,unit->toString(false).c_str(), unit->getCurrCommand()->toString(false).c_str());
Command *command= unit->getCurrCommand();
if(command == NULL) {
throw megaglest_runtime_error("command == NULL");
}
const BuildCommandType *bct= static_cast<const BuildCommandType*>(command->getCommandType());
if(unit->getCurrSkill() != NULL && unit->getCurrSkill()->getClass() != scBuild) {
if(SystemFlags::getSystemSettingType(SystemFlags::debugUnitCommands).enabled) SystemFlags::OutputDebug(SystemFlags::debugUnitCommands,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
//if not building
const UnitType *ut= command->getUnitType();
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());
TravelState tsValue = tsImpossible;
switch(this->game->getGameSettings()->getPathFinderType()) {
case pfBasic:
{
Vec2i buildPos = map->findBestBuildApproach(unit, command->getPos(), ut);
if(SystemFlags::getSystemSettingType(SystemFlags::debugWorldSynch).enabled == true && frameIndex < 0) {
char szBuf[8096]="";
snprintf(szBuf,8096,"[updateBuild] unit->getPos() [%s] command->getPos() [%s] buildPos [%s]",
unit->getPos().getString().c_str(),command->getPos().getString().c_str(),buildPos.getString().c_str());
unit->logSynchData(__FILE__,__LINE__,szBuf);
}
tsValue = pathFinder->findPath(unit, buildPos, NULL, frameIndex);
if(SystemFlags::getSystemSettingType(SystemFlags::debugWorldSynch).enabled == true && frameIndex < 0) {
char szBuf[8096]="";
snprintf(szBuf,8096,"[updateBuild] tsValue: %d",tsValue);
unit->logSynchData(__FILE__,__LINE__,szBuf);
}
}
break;
default:
throw megaglest_runtime_error("detected unsupported pathfinder type!");
}
if(SystemFlags::getSystemSettingType(SystemFlags::debugUnitCommands).enabled) SystemFlags::OutputDebug(SystemFlags::debugUnitCommands,"In [%s::%s Line: %d] tsValue = %d\n",__FILE__,__FUNCTION__,__LINE__,tsValue);
if(frameIndex < 0) {
switch (tsValue) {
case tsMoving:
if(SystemFlags::getSystemSettingType(SystemFlags::debugUnitCommands).enabled) SystemFlags::OutputDebug(SystemFlags::debugUnitCommands,"In [%s::%s Line: %d] tsMoving\n",__FILE__,__FUNCTION__,__LINE__);
unit->setCurrSkill(bct->getMoveSkillType());
break;
case tsArrived:
{
if(SystemFlags::getSystemSettingType(SystemFlags::debugUnitCommands).enabled) SystemFlags::OutputDebug(SystemFlags::debugUnitCommands,"In [%s::%s Line: %d] tsArrived:\n",__FILE__,__FUNCTION__,__LINE__);
//if arrived destination
assert(ut);
if(ut == NULL) {
throw megaglest_runtime_error("ut == NULL");
}
bool canOccupyCell = false;
switch(this->game->getGameSettings()->getPathFinderType()) {
case pfBasic:
if(SystemFlags::getSystemSettingType(SystemFlags::debugUnitCommands).enabled) SystemFlags::OutputDebug(SystemFlags::debugUnitCommands,"In [%s::%s Line: %d] tsArrived about to call map->isFreeCells() for command->getPos() = %s, ut->getSize() = %d\n",__FILE__,__FUNCTION__,__LINE__,command->getPos().getString().c_str(),ut->getSize());
canOccupyCell = map->isFreeCells(command->getPos(), ut->getSize(), fLand);
break;
default:
throw megaglest_runtime_error("detected unsupported pathfinder type!");
}
if(SystemFlags::getSystemSettingType(SystemFlags::debugUnitCommands).enabled) SystemFlags::OutputDebug(SystemFlags::debugUnitCommands,"In [%s::%s Line: %d] canOccupyCell = %d\n",__FILE__,__FUNCTION__,__LINE__,canOccupyCell);
if (canOccupyCell == true) {
const UnitType *builtUnitType= command->getUnitType();
CardinalDir facing = command->getFacing();
UnitPathInterface *newpath = NULL;
switch(this->game->getGameSettings()->getPathFinderType()) {
case pfBasic:
newpath = new UnitPathBasic();
break;
default:
throw megaglest_runtime_error("detected unsupported pathfinder type!");
}
Vec2i buildPos = command->getPos();
Unit *builtUnit= new Unit(world->getNextUnitId(unit->getFaction()), newpath, buildPos, builtUnitType, unit->getFaction(), world->getMap(), facing);
if(SystemFlags::getSystemSettingType(SystemFlags::debugUnitCommands).enabled) SystemFlags::OutputDebug(SystemFlags::debugUnitCommands,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
builtUnit->create();
if(builtUnitType->hasSkillClass(scBeBuilt) == false) {
throw megaglest_runtime_error("Unit [" + builtUnitType->getName(false) + "] has no be_built skill, producer was [" + intToStr(unit->getId()) + " - " + unit->getType()->getName(false) + "].");
}
builtUnit->setCurrSkill(scBeBuilt);
unit->setCurrSkill(bct->getBuildSkillType());
unit->setTarget(builtUnit);
map->prepareTerrain(builtUnit);
if(SystemFlags::getSystemSettingType(SystemFlags::debugUnitCommands).enabled) SystemFlags::OutputDebug(SystemFlags::debugUnitCommands,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
switch(this->game->getGameSettings()->getPathFinderType()) {
case pfBasic:
break;
default:
throw megaglest_runtime_error("detected unsupported pathfinder type!");
}
command->setUnit(builtUnit);
//play start sound
if(unit->getFactionIndex() == world->getThisFactionIndex() ||
(game->getWorld()->showWorldForPlayer(game->getWorld()->getThisTeamIndex()) == true)) {
SoundRenderer::getInstance().playFx(
bct->getStartSound(),
unit->getCurrVector(),
gameCamera->getPos());
}
if(SystemFlags::getSystemSettingType(SystemFlags::debugUnitCommands).enabled) SystemFlags::OutputDebug(SystemFlags::debugUnitCommands,"In [%s::%s Line: %d] unit created for unit [%s]\n",__FILE__,__FUNCTION__,__LINE__,builtUnit->toString(false).c_str());
}
else {
//if there are no free cells
unit->cancelCommand();
unit->setCurrSkill(scStop);
if(unit->getFactionIndex() == world->getThisFactionIndex()) {
console->addStdMessage("BuildingNoPlace");
}
if(SystemFlags::getSystemSettingType(SystemFlags::debugUnitCommands).enabled) SystemFlags::OutputDebug(SystemFlags::debugUnitCommands,"In [%s::%s Line: %d] got BuildingNoPlace\n",__FILE__,__FUNCTION__,__LINE__);
}
}
break;
case tsBlocked:
if(unit->getPath()->isBlocked()) {
unit->cancelCommand();
if(SystemFlags::getSystemSettingType(SystemFlags::debugUnitCommands).enabled) SystemFlags::OutputDebug(SystemFlags::debugUnitCommands,"In [%s::%s Line: %d] got tsBlocked\n",__FILE__,__FUNCTION__,__LINE__);
}
break;
}
}
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());
}
else {
if(SystemFlags::getSystemSettingType(SystemFlags::debugUnitCommands).enabled) SystemFlags::OutputDebug(SystemFlags::debugUnitCommands,"In [%s::%s Line: %d] tsArrived unit = %s\n",__FILE__,__FUNCTION__,__LINE__,unit->toString(false).c_str());
if(frameIndex < 0) {
//if building
Unit *builtUnit = map->getCell(unit->getTargetPos())->getUnit(fLand);
if(builtUnit == NULL) {
builtUnit = map->getCell(unit->getTargetPos())->getUnitWithEmptyCellMap(fLand);
}
if(builtUnit != NULL) {
if(SystemFlags::getSystemSettingType(SystemFlags::debugUnitCommands).enabled) SystemFlags::OutputDebug(SystemFlags::debugUnitCommands,"In [%s::%s Line: %d] builtUnit = %s\n",__FILE__,__FUNCTION__,__LINE__,builtUnit->toString(false).c_str());
}
if(SystemFlags::getSystemSettingType(SystemFlags::debugUnitCommands).enabled) SystemFlags::OutputDebug(SystemFlags::debugUnitCommands,"In [%s::%s Line: %d] builtUnit = [%p]\n",__FILE__,__FUNCTION__,__LINE__,builtUnit);
//if unit is killed while building then u==NULL;
if(builtUnit != NULL && builtUnit != command->getUnit()) {
if(SystemFlags::getSystemSettingType(SystemFlags::debugUnitCommands).enabled) SystemFlags::OutputDebug(SystemFlags::debugUnitCommands,"In [%s::%s Line: %d] builtUnit is not the command's unit!\n",__FILE__,__FUNCTION__,__LINE__);
if(SystemFlags::getSystemSettingType(SystemFlags::debugWorldSynch).enabled == true && frameIndex < 0) {
char szBuf[8096]="";
snprintf(szBuf,8096,"[updateBuild]");
unit->logSynchData(__FILE__,__LINE__,szBuf);
}
unit->setCurrSkill(scStop);
}
else if(builtUnit == NULL || builtUnit->isBuilt()) {
if(SystemFlags::getSystemSettingType(SystemFlags::debugUnitCommands).enabled) SystemFlags::OutputDebug(SystemFlags::debugUnitCommands,"In [%s::%s Line: %d] builtUnit is NULL or ALREADY built\n",__FILE__,__FUNCTION__,__LINE__);
if(SystemFlags::getSystemSettingType(SystemFlags::debugWorldSynch).enabled == true && frameIndex < 0) {
char szBuf[8096]="";
snprintf(szBuf,8096,"[updateBuild]");
unit->logSynchData(__FILE__,__LINE__,szBuf);
}
unit->finishCommand();
unit->setCurrSkill(scStop);
}
else if(builtUnit == NULL || builtUnit->repair()) {
if(SystemFlags::getSystemSettingType(SystemFlags::debugUnitCommands).enabled) SystemFlags::OutputDebug(SystemFlags::debugUnitCommands,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
if(SystemFlags::getSystemSettingType(SystemFlags::debugWorldSynch).enabled == true && frameIndex < 0) {
char szBuf[8096]="";
snprintf(szBuf,8096,"[updateBuild]");
unit->logSynchData(__FILE__,__LINE__,szBuf);
}
const CommandType *ct = (command != NULL ? command->getCommandType() : NULL);
//building finished
unit->finishCommand();
unit->setCurrSkill(scStop);
builtUnit->born(ct);
scriptManager->onUnitCreated(builtUnit);
if(unit->getFactionIndex() == world->getThisFactionIndex() ||
(game->getWorld()->showWorldForPlayer(game->getWorld()->getThisTeamIndex()) == true)) {
SoundRenderer::getInstance().playFx(
bct->getBuiltSound(),
unit->getCurrVector(),
gameCamera->getPos());
}
}
}
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());
}
if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s] Line: %d took msecs: %lld --------------------------- [END OF METHOD] ---------------------------\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis());
}
catch(const exception &ex) {
//setRunningStatus(false);
SystemFlags::OutputDebug(SystemFlags::debugError,"In [%s::%s Line: %d] Error [%s]\n",__FILE__,__FUNCTION__,__LINE__,ex.what());
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
throw megaglest_runtime_error(ex.what());
}
catch(...) {
char szBuf[8096]="";
snprintf(szBuf,8096,"In [%s::%s %d] UNKNOWN error\n",__FILE__,__FUNCTION__,__LINE__);
SystemFlags::OutputDebug(SystemFlags::debugError,szBuf);
throw megaglest_runtime_error(szBuf);
}
}
// ==================== updateHarvest ====================
void UnitUpdater::updateHarvestEmergencyReturn(Unit *unit, int frameIndex) {
try {
if(frameIndex >= 0) {
return;
}
if(SystemFlags::getSystemSettingType(SystemFlags::debugWorldSynch).enabled == true && frameIndex < 0) {
char szBuf[8096]="";
snprintf(szBuf,8096,"[updateHarvestEmergencyReturn]");
unit->logSynchDataThreaded(extractFileFromDirectoryPath(__FILE__).c_str(),__LINE__,szBuf);
}
//printf("\n#1 updateHarvestEmergencyReturn\n");
Command *command= unit->getCurrCommand();
if(command != NULL) {
//printf("\n#2 updateHarvestEmergencyReturn\n");
//const HarvestCommandType *hct= dynamic_cast<const HarvestCommandType*>((command != NULL ? command->getCommandType() : NULL));
//if(hct != NULL) {
{
//printf("\n#3 updateHarvestEmergencyReturn\n");
const Vec2i unitTargetPos = command->getPos();
Cell *cell= map->getCell(unitTargetPos);
if(cell != NULL && cell->getUnit(unit->getCurrField()) != NULL) {
//printf("\n#4 updateHarvestEmergencyReturn\n");
Unit *targetUnit = cell->getUnit(unit->getCurrField());
if(targetUnit != NULL) {
//printf("\n#5 updateHarvestEmergencyReturn\n");
// Check if we can return whatever resources we have
if(targetUnit->getFactionIndex() == unit->getFactionIndex() &&
targetUnit->isOperative() == true && unit->getLoadType() != NULL &&
targetUnit->getType() != NULL && targetUnit->getType()->getStore(unit->getLoadType()) > 0) {
//printf("\n#6 updateHarvestEmergencyReturn\n");
const HarvestCommandType *previousHarvestCmd = unit->getType()->getFirstHarvestCommand(unit->getLoadType(),unit->getFaction());
if(previousHarvestCmd != NULL) {
//printf("\n\n#1a return harvested resources\n\n");
NetworkCommand networkCommand(this->world,nctGiveCommand, unit->getId(), previousHarvestCmd->getId(), unit->getLastHarvestedResourcePos(),
-1, Unit::invalidId, -1, false, cst_None, -1, -1);
if(SystemFlags::getSystemSettingType(SystemFlags::debugUnitCommands).enabled) SystemFlags::OutputDebug(SystemFlags::debugUnitCommands,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
Command* new_command= this->game->getCommander()->buildCommand(&networkCommand);
new_command->setStateType(cst_EmergencyReturnResource);
new_command->setStateValue(1);
std::pair<CommandResult,string> cr= unit->checkCommand(new_command);
if(cr.first == crSuccess) {
//printf("\n\n#1b return harvested resources\n\n");
if(SystemFlags::getSystemSettingType(SystemFlags::debugUnitCommands).enabled) SystemFlags::OutputDebug(SystemFlags::debugUnitCommands,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
unit->replaceCurrCommand(new_command);
unit->setCurrSkill(previousHarvestCmd->getStopLoadedSkillType()); // make sure we use the right harvest animation
}
else {
//printf("\n\n#1c return harvested resources\n\n");
if(SystemFlags::getSystemSettingType(SystemFlags::debugUnitCommands).enabled) SystemFlags::OutputDebug(SystemFlags::debugUnitCommands,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
delete new_command;
unit->setCurrSkill(scStop);
unit->finishCommand();
}
}
}
}
}
}
}
}
catch(const exception &ex) {
//setRunningStatus(false);
SystemFlags::OutputDebug(SystemFlags::debugError,"In [%s::%s Line: %d] Error [%s]\n",__FILE__,__FUNCTION__,__LINE__,ex.what());
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
throw megaglest_runtime_error(ex.what());
}
catch(...) {
char szBuf[8096]="";
snprintf(szBuf,8096,"In [%s::%s %d] UNKNOWN error\n",__FILE__,__FUNCTION__,__LINE__);
SystemFlags::OutputDebug(SystemFlags::debugError,szBuf);
throw megaglest_runtime_error(szBuf);
}
}
void UnitUpdater::updateHarvest(Unit *unit, int frameIndex) {
try {
if(SystemFlags::getSystemSettingType(SystemFlags::debugWorldSynch).enabled == true && frameIndex < 0) {
char szBuf[8096]="";
snprintf(szBuf,8096,"[updateHarvest]");
unit->logSynchData(extractFileFromDirectoryPath(__FILE__).c_str(),__LINE__,szBuf);
}
Chrono chrono;
if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled) chrono.start();
Command *command= unit->getCurrCommand();
if(command == NULL) {
throw megaglest_runtime_error("command == NULL");
}
const HarvestCommandType *hct= dynamic_cast<const HarvestCommandType*>(command->getCommandType());
if(hct == NULL) {
throw megaglest_runtime_error("hct == NULL");
}
Vec2i targetPos(-1);
//TravelState tsValue = tsImpossible;
//UnitPathInterface *path= unit->getPath();
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());
//printf("In UpdateHarvest [%d - %s] unit->getCurrSkill()->getClass() = %d\n",unit->getId(),unit->getType()->getName().c_str(),unit->getCurrSkill()->getClass());
Resource *harvestResource = NULL;
SurfaceCell *sc = map->getSurfaceCell(Map::toSurfCoords(command->getPos()));
if(sc != NULL) {
harvestResource = sc->getResource();
}
if(unit->getCurrSkill() != NULL && unit->getCurrSkill()->getClass() != scHarvest) {
bool forceReturnToStore = (command != NULL &&
command->getStateType() == cst_EmergencyReturnResource && command->getStateValue() == 1);
//if not working
if(unit->getLoadCount() == 0 ||
(forceReturnToStore == false && unit->getLoadType() != NULL &&
harvestResource != NULL && (unit->getLoadCount() < hct->getMaxLoad()) &&
harvestResource->getType() != NULL && unit->getLoadType() == harvestResource->getType())) {
//if not loaded go for resources
SurfaceCell *sc = map->getSurfaceCell(Map::toSurfCoords(command->getPos()));
if(sc != NULL) {
Resource *r = sc->getResource();
if(r != NULL && hct != NULL && hct->canHarvest(r->getType())) {
//if can harvest dest. pos
bool canHarvestDestPos = false;
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());
switch(this->game->getGameSettings()->getPathFinderType()) {
case pfBasic:
{
const bool newHarvestPath = false;
bool isNearResource = false;
Vec2i clickPos = command->getOriginalPos();
if(newHarvestPath == true) {
isNearResource = map->isResourceNear(frameIndex,unit->getPos(), r->getType(), targetPos,unit->getType()->getSize(),unit, false,&clickPos);
}
else {
isNearResource = map->isResourceNear(frameIndex,unit->getPos(), r->getType(), targetPos,unit->getType()->getSize(),unit);
}
if(isNearResource == true) {
if((unit->getPos().dist(command->getPos()) < harvestDistance || unit->getPos().dist(targetPos) < harvestDistance) && isNearResource == true) {
canHarvestDestPos = true;
}
}
else if(newHarvestPath == true) {
if(clickPos != command->getOriginalPos()) {
//printf("%%----------- unit [%s - %d] CHANGING RESOURCE POS from [%s] to [%s]\n",unit->getFullName().c_str(),unit->getId(),command->getOriginalPos().getString().c_str(),clickPos.getString().c_str());
if(frameIndex < 0) {
if(SystemFlags::getSystemSettingType(SystemFlags::debugWorldSynch).enabled == true && frameIndex < 0) {
char szBuf[8096]="";
snprintf(szBuf,8096,"[updateHarvest] clickPos [%s]",clickPos.getString().c_str());
unit->logSynchData(extractFileFromDirectoryPath(__FILE__).c_str(),__LINE__,szBuf);
}
command->setPos(clickPos);
}
}
}
}
break;
default:
throw megaglest_runtime_error("detected unsupported pathfinder type!");
}
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());
if (canHarvestDestPos == true ) {
if(frameIndex < 0) {
if(SystemFlags::getSystemSettingType(SystemFlags::debugWorldSynch).enabled == true && frameIndex < 0) {
char szBuf[8096]="";
snprintf(szBuf,8096,"[updateHarvest]");
unit->logSynchData(extractFileFromDirectoryPath(__FILE__).c_str(),__LINE__,szBuf);
}
unit->setLastHarvestResourceTarget(NULL);
}
canHarvestDestPos = (map->getSurfaceCell(Map::toSurfCoords(targetPos)) != NULL && map->getSurfaceCell(Map::toSurfCoords(targetPos))->getResource() != NULL && map->getSurfaceCell(Map::toSurfCoords(targetPos))->getResource()->getType() != NULL);
if(canHarvestDestPos == true) {
if(frameIndex < 0) {
//if it finds resources it starts harvesting
unit->setCurrSkill(hct->getHarvestSkillType());
unit->setTargetPos(targetPos);
command->setPos(targetPos);
if(unit->getLoadType() == NULL || harvestResource == NULL ||
harvestResource->getType() == NULL || unit->getLoadType() != harvestResource->getType()) {
unit->setLoadCount(0);
}
unit->getFaction()->addResourceTargetToCache(targetPos);
switch(this->game->getGameSettings()->getPathFinderType()) {
case pfBasic:
unit->setLoadType(r->getType());
break;
default:
throw megaglest_runtime_error("detected unsupported pathfinder type!");
}
if(SystemFlags::getSystemSettingType(SystemFlags::debugWorldSynch).enabled == true && frameIndex < 0) {
char szBuf[8096]="";
snprintf(szBuf,8096,"[updateHarvest] targetPos [%s]",targetPos.getString().c_str());
unit->logSynchData(extractFileFromDirectoryPath(__FILE__).c_str(),__LINE__,szBuf);
}
}
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());
}
}
if(canHarvestDestPos == false) {
if(frameIndex < 0) {
if(SystemFlags::getSystemSettingType(SystemFlags::debugWorldSynch).enabled == true && frameIndex < 0) {
char szBuf[8096]="";
snprintf(szBuf,8096,"[updateHarvest] targetPos [%s]",targetPos.getString().c_str());
unit->logSynchData(extractFileFromDirectoryPath(__FILE__).c_str(),__LINE__,szBuf);
}
unit->setLastHarvestResourceTarget(&targetPos);
}
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());
if(SystemFlags::getSystemSettingType(SystemFlags::debugWorldSynch).enabled == true && frameIndex < 0) {
char szBuf[8096]="";
snprintf(szBuf,8096,"[updateHarvest] unit->getPos() [%s] command->getPos() [%s]",
unit->getPos().getString().c_str(),command->getPos().getString().c_str());
unit->logSynchData(__FILE__,__LINE__,szBuf);
}
//if not continue walking
bool wasStuck = false;
TravelState tsValue = tsImpossible;
switch(this->game->getGameSettings()->getPathFinderType()) {
case pfBasic:
tsValue = pathFinder->findPath(unit, command->getPos(), &wasStuck, frameIndex);
if (tsValue == tsMoving && frameIndex < 0) {
unit->setCurrSkill(hct->getMoveSkillType());
}
break;
default:
throw megaglest_runtime_error("detected unsupported pathfinder type!");
}
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());
// If the unit is blocked or Even worse 'stuck' then try to
// find the same resource type elsewhere, but close by
if((wasStuck == true || tsValue == tsBlocked) && unit->isAlive() == true) {
switch(this->game->getGameSettings()->getPathFinderType()) {
case pfBasic:
{
bool isNearResource = map->isResourceNear(frameIndex,unit->getPos(), r->getType(), targetPos,unit->getType()->getSize(),unit,true);
if(isNearResource == true) {
if((unit->getPos().dist(command->getPos()) < harvestDistance || unit->getPos().dist(targetPos) < harvestDistance) && isNearResource == true) {
canHarvestDestPos = true;
}
}
}
break;
default:
throw megaglest_runtime_error("detected unsupported pathfinder type!");
}
if (canHarvestDestPos == true) {
if(frameIndex < 0) {
unit->setLastHarvestResourceTarget(NULL);
}
canHarvestDestPos = (map->getSurfaceCell(Map::toSurfCoords(targetPos)) != NULL && map->getSurfaceCell(Map::toSurfCoords(targetPos))->getResource() != NULL && map->getSurfaceCell(Map::toSurfCoords(targetPos))->getResource()->getType() != NULL);
if(canHarvestDestPos == true) {
if(frameIndex < 0) {
//if it finds resources it starts harvesting
unit->setCurrSkill(hct->getHarvestSkillType());
unit->setTargetPos(targetPos);
command->setPos(targetPos);
if(unit->getLoadType() == NULL || harvestResource == NULL ||
harvestResource->getType() == NULL || unit->getLoadType() != harvestResource->getType()) {
unit->setLoadCount(0);
}
unit->getFaction()->addResourceTargetToCache(targetPos);
switch(this->game->getGameSettings()->getPathFinderType()) {
case pfBasic:
unit->setLoadType(r->getType());
break;
default:
throw megaglest_runtime_error("detected unsupported pathfinder type!");
}
}
}
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());
}
if(canHarvestDestPos == false) {
if(frameIndex < 0) {
unit->setLastHarvestResourceTarget(&targetPos);
}
if(targetPos.x >= 0) {
//if not continue walking
if(SystemFlags::getSystemSettingType(SystemFlags::debugWorldSynch).enabled == true && frameIndex < 0) {
char szBuf[8096]="";
snprintf(szBuf,8096,"[updateHarvest #2] unit->getPos() [%s] command->getPos() [%s] targetPos [%s]",
unit->getPos().getString().c_str(),command->getPos().getString().c_str(),targetPos.getString().c_str());
unit->logSynchData(__FILE__,__LINE__,szBuf);
}
wasStuck = false;
TravelState tsValue = tsImpossible;
switch(this->game->getGameSettings()->getPathFinderType()) {
case pfBasic:
tsValue = pathFinder->findPath(unit, targetPos, &wasStuck, frameIndex);
if (tsValue == tsMoving && frameIndex < 0) {
unit->setCurrSkill(hct->getMoveSkillType());
command->setPos(targetPos);
}
break;
default:
throw megaglest_runtime_error("detected unsupported pathfinder type!");
}
}
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());
if(wasStuck == true && frameIndex < 0) {
//if can't harvest, search for another resource
unit->setCurrSkill(scStop);
if(searchForResource(unit, hct) == false) {
unit->finishCommand();
}
}
}
}
}
}
else {
if(frameIndex < 0) {
//if can't harvest, search for another resource
unit->setCurrSkill(scStop);
if(searchForResource(unit, hct) == false) {
unit->finishCommand();
}
}
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());
}
}
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());
}
else {
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());
//if loaded, return to store
Unit *store= world->nearestStore(unit->getPos(), unit->getFaction()->getIndex(), unit->getLoadType());
if(store != NULL) {
if(SystemFlags::getSystemSettingType(SystemFlags::debugWorldSynch).enabled == true && frameIndex < 0) {
char szBuf[8096]="";
snprintf(szBuf,8096,"[updateHarvest #3] unit->getPos() [%s] store->getCenteredPos() [%s]",
unit->getPos().getString().c_str(),store->getCenteredPos().getString().c_str());
unit->logSynchData(__FILE__,__LINE__,szBuf);
}
TravelState tsValue = tsImpossible;
switch(this->game->getGameSettings()->getPathFinderType()) {
case pfBasic:
tsValue = pathFinder->findPath(unit, store->getCenteredPos(), NULL, frameIndex);
break;
default:
throw megaglest_runtime_error("detected unsupported pathfinder type!");
}
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());
if(frameIndex < 0) {
switch(tsValue) {
case tsMoving:
{
if (hct->canHarvest(unit->getLoadType()) == false) {
// hct has changed to a different harvest command.
const HarvestCommandType *previousHarvestCmd = unit->getType()->getFirstHarvestCommand(unit->getLoadType(),unit->getFaction());
if(previousHarvestCmd != NULL) {
//printf("\n\n#1\n\n");
unit->setCurrSkill(previousHarvestCmd->getMoveLoadedSkillType()); // make sure we use the right harvest animation
}
else {
//printf("\n\n#2\n\n");
unit->setCurrSkill(hct->getMoveLoadedSkillType());
}
}
else {
unit->setCurrSkill(hct->getMoveLoadedSkillType());
}
}
break;
default:
break;
}
//world->changePosCells(unit,unit->getPos()+unit->getDest());
if(map->isNextTo(unit, store)) {
//update resources
int resourceAmount= unit->getLoadCount();
if(unit->getFaction()->getCpuControl())
{
int resourceMultiplierIndex=game->getGameSettings()->getResourceMultiplierIndex(unit->getFaction()->getIndex());
resourceAmount=(resourceAmount* (resourceMultiplierIndex +5))/10;
}
unit->getFaction()->incResourceAmount(unit->getLoadType(), resourceAmount);
world->getStats()->harvest(unit->getFactionIndex(), resourceAmount);
scriptManager->onResourceHarvested();
//if next to a store unload resources
unit->getPath()->clear();
unit->setCurrSkill(scStop);
unit->setLoadCount(0);
command->setPosToOriginalPos();
}
}
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());
}
else {
if(frameIndex < 0) {
unit->finishCommand();
}
}
}
}
else {
if(frameIndex < 0) {
//if working
//unit->setLastHarvestResourceTarget(NULL);
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());
const Vec2i unitTargetPos = unit->getTargetPos();
SurfaceCell *sc= map->getSurfaceCell(Map::toSurfCoords(unitTargetPos));
Resource *r= sc->getResource();
if (r != NULL) {
if (hct->canHarvest(r->getType()) == false ||
r->getType()->getName() != unit->getLoadType()->getName()) {
// hct has changed to a different harvest command.
if(r->getType()->getName() != unit->getLoadType()->getName()) {
const HarvestCommandType *previousHarvestCmd = unit->getType()->getFirstHarvestCommand(unit->getLoadType(),unit->getFaction());
if(previousHarvestCmd != NULL) {
//printf("\n\n#1\n\n");
unit->setCurrSkill(previousHarvestCmd->getStopLoadedSkillType()); // make sure we use the right harvest animation
}
else {
//printf("\n\n#2\n\n");
unit->setCurrSkill(hct->getStopLoadedSkillType());
}
}
else if(hct->canHarvest(r->getType()) == false) {
const HarvestCommandType *previousHarvestCmd = unit->getType()->getFirstHarvestCommand(unit->getLoadType(),unit->getFaction());
if(previousHarvestCmd != NULL) {
//printf("\n\n#3\n\n");
unit->setCurrSkill(previousHarvestCmd->getStopLoadedSkillType()); // make sure we use the right harvest animation
}
else {
//printf("\n\n#4\n\n");
unit->setCurrSkill(hct->getStopLoadedSkillType());
}
}
else {
//printf("\n\n#5 [%s] [%s]\n\n",r->getType()->getName().c_str(),unit->getLoadType()->getName().c_str());
unit->setCurrSkill(hct->getStopLoadedSkillType()); // this is actually the wrong animation
}
unit->getPath()->clear();
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());
}
else {
// if there is a resource, continue working, until loaded
unit->update2();
unit->setLastHarvestedResourcePos(unitTargetPos);
if (unit->getProgress2() >= hct->getHitsPerUnit()) {
if (unit->getLoadCount() < hct->getMaxLoad()) {
unit->setProgress2(0);
unit->setLoadCount(unit->getLoadCount() + 1);
//if resource exausted, then delete it and stop
if (sc->decAmount(1)) {
//const ResourceType *rt = r->getType();
sc->deleteResource();
world->removeResourceTargetFromCache(unitTargetPos);
switch(this->game->getGameSettings()->getPathFinderType()) {
case pfBasic:
break;
default:
throw megaglest_runtime_error("detected unsupported pathfinder type!");
}
//printf("\n\n#6\n\n");
unit->setCurrSkill(hct->getStopLoadedSkillType());
}
}
if (unit->getLoadCount() >= hct->getMaxLoad()) {
//printf("\n\n#7\n\n");
unit->setCurrSkill(hct->getStopLoadedSkillType());
unit->getPath()->clear();
}
}
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());
}
}
else {
//if there is no resource, just stop
//printf("\n\n#8\n\n");
unit->setCurrSkill(hct->getStopLoadedSkillType());
}
}
}
if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s] Line: %d took msecs: %lld --------------------------- [END OF METHOD] ---------------------------\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis());
}
catch(const exception &ex) {
//setRunningStatus(false);
SystemFlags::OutputDebug(SystemFlags::debugError,"In [%s::%s Line: %d] Error [%s]\n",__FILE__,__FUNCTION__,__LINE__,ex.what());
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
throw megaglest_runtime_error(ex.what());
}
catch(...) {
char szBuf[8096]="";
snprintf(szBuf,8096,"In [%s::%s %d] UNKNOWN error\n",__FILE__,__FUNCTION__,__LINE__);
SystemFlags::OutputDebug(SystemFlags::debugError,szBuf);
throw megaglest_runtime_error(szBuf);
}
}
void UnitUpdater::SwapActiveCommand(Unit *unitSrc, Unit *unitDest) {
if(SystemFlags::getSystemSettingType(SystemFlags::debugUnitCommands).enabled) SystemFlags::OutputDebug(SystemFlags::debugUnitCommands,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
if(unitSrc->getCommandSize() > 0 && unitDest->getCommandSize() > 0) {
if(SystemFlags::getSystemSettingType(SystemFlags::debugUnitCommands).enabled) SystemFlags::OutputDebug(SystemFlags::debugUnitCommands,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
Command *cmd1 = unitSrc->getCurrCommand();
Command *cmd2 = unitDest->getCurrCommand();
unitSrc->replaceCurrCommand(cmd2);
unitDest->replaceCurrCommand(cmd1);
}
if(SystemFlags::getSystemSettingType(SystemFlags::debugUnitCommands).enabled) SystemFlags::OutputDebug(SystemFlags::debugUnitCommands,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
}
void UnitUpdater::SwapActiveCommandState(Unit *unit, CommandStateType commandStateType,
const CommandType *commandType,
int originalValue,int newValue) {
if(SystemFlags::getSystemSettingType(SystemFlags::debugUnitCommands).enabled) SystemFlags::OutputDebug(SystemFlags::debugUnitCommands,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
if(commandStateType == cst_linkedUnit) {
if(dynamic_cast<const BuildCommandType *>(commandType) != NULL) {
for(int i = 0; i < unit->getFaction()->getUnitCount(); ++i) {
Unit *peerUnit = unit->getFaction()->getUnit(i);
if(peerUnit != NULL) {
if(peerUnit->getCommandSize() > 0 ) {
if(SystemFlags::getSystemSettingType(SystemFlags::debugUnitCommands).enabled) SystemFlags::OutputDebug(SystemFlags::debugUnitCommands,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
Command *peerCommand = peerUnit->getCurrCommand();
//const BuildCommandType *bct = dynamic_cast<const BuildCommandType*>(peerCommand->getCommandType());
//if(bct != NULL) {
if(peerCommand != NULL) {
if(SystemFlags::getSystemSettingType(SystemFlags::debugUnitCommands).enabled) SystemFlags::OutputDebug(SystemFlags::debugUnitCommands,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
//if(command->getPos() == peerCommand->getPos()) {
if( peerCommand->getStateType() == commandStateType &&
peerCommand->getStateValue() == originalValue) {
if(SystemFlags::getSystemSettingType(SystemFlags::debugUnitCommands).enabled) SystemFlags::OutputDebug(SystemFlags::debugUnitCommands,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
peerCommand->setStateValue(newValue);
}
}
}
}
}
}
}
if(SystemFlags::getSystemSettingType(SystemFlags::debugUnitCommands).enabled) SystemFlags::OutputDebug(SystemFlags::debugUnitCommands,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
}
Unit * UnitUpdater::findPeerUnitBuilder(Unit *unit) {
if(SystemFlags::getSystemSettingType(SystemFlags::debugUnitCommands).enabled) SystemFlags::OutputDebug(SystemFlags::debugUnitCommands,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
Unit *foundUnitBuilder = NULL;
if(unit->getCommandSize() > 0 ) {
Command *command = unit->getCurrCommand();
if(command != NULL) {
const RepairCommandType *rct= dynamic_cast<const RepairCommandType*>(command->getCommandType());
if(rct != NULL && command->getStateType() == cst_linkedUnit) {
if(SystemFlags::getSystemSettingType(SystemFlags::debugUnitCommands).enabled) SystemFlags::OutputDebug(SystemFlags::debugUnitCommands,"In [%s::%s Line: %d] looking for command->getStateValue() = %d\n",__FILE__,__FUNCTION__,__LINE__,command->getStateValue());
Unit *firstLinkedPeerRepairer = NULL;
for(int i = 0; i < unit->getFaction()->getUnitCount(); ++i) {
Unit *peerUnit = unit->getFaction()->getUnit(i);
if(peerUnit != NULL) {
if(peerUnit->getCommandSize() > 0 ) {
if(SystemFlags::getSystemSettingType(SystemFlags::debugUnitCommands).enabled) SystemFlags::OutputDebug(SystemFlags::debugUnitCommands,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
Command *peerCommand = peerUnit->getCurrCommand();
const BuildCommandType *bct = dynamic_cast<const BuildCommandType*>(peerCommand->getCommandType());
if(bct != NULL) {
if(SystemFlags::getSystemSettingType(SystemFlags::debugUnitCommands).enabled) SystemFlags::OutputDebug(SystemFlags::debugUnitCommands,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
if(command->getStateValue() == peerUnit->getId()) {
if(SystemFlags::getSystemSettingType(SystemFlags::debugUnitCommands).enabled) SystemFlags::OutputDebug(SystemFlags::debugUnitCommands,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
foundUnitBuilder = peerUnit;
break;
}
}
else {
if(SystemFlags::getSystemSettingType(SystemFlags::debugUnitCommands).enabled) SystemFlags::OutputDebug(SystemFlags::debugUnitCommands,"In [%s::%s Line: %d] **peer NOT building**, peerUnit = [%s]\n",__FILE__,__FUNCTION__,__LINE__,peerUnit->toString(false).c_str());
if(firstLinkedPeerRepairer == NULL) {
const RepairCommandType *prct = dynamic_cast<const RepairCommandType*>(peerCommand->getCommandType());
if(prct != NULL) {
if(SystemFlags::getSystemSettingType(SystemFlags::debugUnitCommands).enabled) SystemFlags::OutputDebug(SystemFlags::debugUnitCommands,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
if(unit->getId() != peerUnit->getId() && command->getStateValue() == peerUnit->getId()) {
if(SystemFlags::getSystemSettingType(SystemFlags::debugUnitCommands).enabled) SystemFlags::OutputDebug(SystemFlags::debugUnitCommands,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
firstLinkedPeerRepairer = peerUnit;
}
}
}
}
}
}
}
if(foundUnitBuilder == NULL && firstLinkedPeerRepairer != NULL) {
foundUnitBuilder = firstLinkedPeerRepairer;
}
}
}
}
if(SystemFlags::getSystemSettingType(SystemFlags::debugUnitCommands).enabled) SystemFlags::OutputDebug(SystemFlags::debugUnitCommands,"In [%s::%s Line: %d] returning foundUnitBuilder = [%s]\n",__FILE__,__FUNCTION__,__LINE__,(foundUnitBuilder != NULL ? foundUnitBuilder->toString(false).c_str() : "null"));
return foundUnitBuilder;
}
// ==================== updateRepair ====================
void UnitUpdater::updateRepair(Unit *unit, int frameIndex) {
try {
// Nothing to do
if(frameIndex >= 0) {
clearUnitPrecache(unit);
return;
}
if(SystemFlags::getSystemSettingType(SystemFlags::debugWorldSynch).enabled == true && frameIndex < 0) {
char szBuf[8096]="";
snprintf(szBuf,8096,"[updateRepair]");
unit->logSynchData(extractFileFromDirectoryPath(__FILE__).c_str(),__LINE__,szBuf);
}
Chrono chrono;
if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled) chrono.start();
if(SystemFlags::getSystemSettingType(SystemFlags::debugUnitCommands).enabled) SystemFlags::OutputDebug(SystemFlags::debugUnitCommands,"In [%s::%s Line: %d] unit = %p\n",__FILE__,__FUNCTION__,__LINE__,unit);
//if(unit != NULL) {
if(SystemFlags::getSystemSettingType(SystemFlags::debugUnitCommands).enabled) SystemFlags::OutputDebug(SystemFlags::debugUnitCommands,"In [%s::%s Line: %d] unit doing the repair [%s] - %d\n",__FILE__,__FUNCTION__,__LINE__,unit->getFullName(false).c_str(),unit->getId());
//}
Command *command= unit->getCurrCommand();
if(command == NULL) {
throw megaglest_runtime_error("command == NULL");
}
const RepairCommandType *rct= static_cast<const RepairCommandType*>(command->getCommandType());
const CommandType *ct = (command != NULL ? command->getCommandType() : NULL);
if(SystemFlags::getSystemSettingType(SystemFlags::debugUnitCommands).enabled) SystemFlags::OutputDebug(SystemFlags::debugUnitCommands,"In [%s::%s Line: %d] rct = %p\n",__FILE__,__FUNCTION__,__LINE__,rct);
Unit *repaired = (command != NULL ? map->getCell(command->getPos())->getUnitWithEmptyCellMap(fLand) : NULL);
if(repaired == NULL && command != NULL) {
repaired = map->getCell(command->getPos())->getUnit(fLand);
}
if(repaired != NULL) {
if(SystemFlags::getSystemSettingType(SystemFlags::debugUnitCommands).enabled) SystemFlags::OutputDebug(SystemFlags::debugUnitCommands,"In [%s::%s Line: %d] unit to repair [%s] - %d\n",__FILE__,__FUNCTION__,__LINE__,repaired->getFullName(false).c_str(),repaired->getId());
}
if(chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s] Line: %d took msecs: %lld\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis());
// Check if the 'repaired' unit is actually the peer unit in a multi-build?
Unit *peerUnitBuilder = findPeerUnitBuilder(unit);
if(peerUnitBuilder != NULL) {
SystemFlags::OutputDebug(SystemFlags::debugUnitCommands,"In [%s::%s Line: %d] unit peer [%s] - %d\n",__FILE__,__FUNCTION__,__LINE__,peerUnitBuilder->getFullName(false).c_str(),peerUnitBuilder->getId());
}
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());
// Ensure we have the right unit to repair
if(peerUnitBuilder != NULL) {
if(SystemFlags::getSystemSettingType(SystemFlags::debugUnitCommands).enabled) SystemFlags::OutputDebug(SystemFlags::debugUnitCommands,"In [%s::%s Line: %d] peerUnitBuilder = %p\n",__FILE__,__FUNCTION__,__LINE__,peerUnitBuilder);
if(peerUnitBuilder->getCurrCommand()->getUnit() != NULL) {
if(SystemFlags::getSystemSettingType(SystemFlags::debugUnitCommands).enabled) SystemFlags::OutputDebug(SystemFlags::debugUnitCommands,"In [%s::%s Line: %d] peerbuilder's unitid = %d\n",__FILE__,__FUNCTION__,__LINE__,peerUnitBuilder->getCurrCommand()->getUnit()->getId());
repaired = peerUnitBuilder->getCurrCommand()->getUnit();
}
}
bool nextToRepaired = repaired != NULL && map->isNextTo(unit, repaired);
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());
peerUnitBuilder = NULL;
if(repaired == NULL) {
peerUnitBuilder = findPeerUnitBuilder(unit);
if(peerUnitBuilder != NULL) {
if(SystemFlags::getSystemSettingType(SystemFlags::debugUnitCommands).enabled) SystemFlags::OutputDebug(SystemFlags::debugUnitCommands,"In [%s::%s Line: %d] peerUnitBuilder = %p\n",__FILE__,__FUNCTION__,__LINE__,peerUnitBuilder);
if(peerUnitBuilder->getCurrCommand()->getUnit() != NULL) {
if(SystemFlags::getSystemSettingType(SystemFlags::debugUnitCommands).enabled) SystemFlags::OutputDebug(SystemFlags::debugUnitCommands,"In [%s::%s Line: %d] peerbuilder's unitid = %d\n",__FILE__,__FUNCTION__,__LINE__,peerUnitBuilder->getCurrCommand()->getUnit()->getId());
repaired = peerUnitBuilder->getCurrCommand()->getUnit();
nextToRepaired = repaired != NULL && map->isNextTo(unit, repaired);
}
else {
if(SystemFlags::getSystemSettingType(SystemFlags::debugUnitCommands).enabled) SystemFlags::OutputDebug(SystemFlags::debugUnitCommands,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
Vec2i buildPos = map->findBestBuildApproach(unit, command->getPos(), peerUnitBuilder->getCurrCommand()->getUnitType());
//nextToRepaired= (unit->getPos() == (command->getPos()-Vec2i(1)));
nextToRepaired = (unit->getPos() == buildPos);
if(SystemFlags::getSystemSettingType(SystemFlags::debugUnitCommands).enabled) SystemFlags::OutputDebug(SystemFlags::debugUnitCommands,"In [%s::%s Line: %d] peerUnitBuilder = %p, nextToRepaired = %d\n",__FILE__,__FUNCTION__,__LINE__,peerUnitBuilder,nextToRepaired);
if(nextToRepaired == true) {
if(SystemFlags::getSystemSettingType(SystemFlags::debugUnitCommands).enabled) SystemFlags::OutputDebug(SystemFlags::debugUnitCommands,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
Command *peerCommand = peerUnitBuilder->getCurrCommand();
const RepairCommandType *rct = dynamic_cast<const RepairCommandType*>(peerCommand->getCommandType());
// If the peer is also scheduled to do a repair we CANNOT swap their commands or
// it will result in a stack overflow as each swaps the others repair command.
// We must convert this unit's repair into a build right now!
if(rct != NULL) {
if(SystemFlags::getSystemSettingType(SystemFlags::debugUnitCommands).enabled) SystemFlags::OutputDebug(SystemFlags::debugUnitCommands,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
const CommandType *ctbuild = unit->getType()->getFirstCtOfClass(ccBuild);
NetworkCommand networkCommand(this->world,nctGiveCommand, unit->getId(), ctbuild->getId(), command->getPos(),
command->getUnitType()->getId(), -1, CardinalDir::NORTH, true, command->getStateType(),
command->getStateValue());
if(SystemFlags::getSystemSettingType(SystemFlags::debugUnitCommands).enabled) SystemFlags::OutputDebug(SystemFlags::debugUnitCommands,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
Command* command= this->game->getCommander()->buildCommand(&networkCommand);
std::pair<CommandResult,string> cr= unit->checkCommand(command);
if(cr.first == crSuccess) {
if(SystemFlags::getSystemSettingType(SystemFlags::debugUnitCommands).enabled) SystemFlags::OutputDebug(SystemFlags::debugUnitCommands,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
unit->replaceCurrCommand(command);
}
else {
if(SystemFlags::getSystemSettingType(SystemFlags::debugUnitCommands).enabled) SystemFlags::OutputDebug(SystemFlags::debugUnitCommands,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
delete command;
unit->setCurrSkill(scStop);
unit->finishCommand();
}
}
else {
CommandStateType commandStateType = unit->getCurrCommand()->getStateType();
SwapActiveCommand(unit,peerUnitBuilder);
int oldPeerUnitId = peerUnitBuilder->getId();
int newPeerUnitId = unit->getId();
SwapActiveCommandState(unit,commandStateType,unit->getCurrCommand()->getCommandType(),oldPeerUnitId,newPeerUnitId);
// Give the swapped unit a fresh chance to help build in case they
// were or are about to be blocked
peerUnitBuilder->getPath()->clear();
peerUnitBuilder->setRetryCurrCommandCount(1);
updateUnitCommand(unit,-1);
}
return;
}
}
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());
}
}
else {
if(SystemFlags::getSystemSettingType(SystemFlags::debugUnitCommands).enabled) SystemFlags::OutputDebug(SystemFlags::debugUnitCommands,"In [%s::%s Line: %d] unit to repair[%s]\n",__FILE__,__FUNCTION__,__LINE__,repaired->getFullName(false).c_str());
}
if(SystemFlags::getSystemSettingType(SystemFlags::debugUnitCommands).enabled) SystemFlags::OutputDebug(SystemFlags::debugUnitCommands,"In [%s::%s Line: %d] repaired = %p, nextToRepaired = %d, unit->getCurrSkill()->getClass() = %d\n",__FILE__,__FUNCTION__,__LINE__,repaired,nextToRepaired,unit->getCurrSkill()->getClass());
//UnitPathInterface *path= unit->getPath();
if(unit->getCurrSkill()->getClass() != scRepair ||
(nextToRepaired == false && peerUnitBuilder == NULL)) {
if(command == NULL) {
throw megaglest_runtime_error("command == NULL");
}
Vec2i repairPos = command->getPos();
bool startRepairing = (repaired != NULL && rct->isRepairableUnitType(repaired->getType()) && repaired->isDamaged());
if(startRepairing == true) {
//printf("STARTING REPAIR, unit [%s - %d] for unit [%s - %d]\n",unit->getType()->getName().c_str(),unit->getId(),repaired->getType()->getName().c_str(),repaired->getId());
// for(unsigned int i = 0; i < rct->getRepairCount(); ++i) {
// const UnitType *rUnit = rct->getRepair(i);
// printf("Can repair unittype [%s]\n",rUnit->getName().c_str());
// }
}
if(SystemFlags::getSystemSettingType(SystemFlags::debugUnitCommands).enabled) SystemFlags::OutputDebug(SystemFlags::debugUnitCommands,"In [%s::%s Line: %d] repairPos = %s, startRepairing = %d\n",__FILE__,__FUNCTION__,__LINE__,repairPos.getString().c_str(),startRepairing);
if(startRepairing == false && peerUnitBuilder != NULL) {
if(SystemFlags::getSystemSettingType(SystemFlags::debugUnitCommands).enabled) SystemFlags::OutputDebug(SystemFlags::debugUnitCommands,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
startRepairing = true;
// Since the unit to be built is not yet existing we need to tell the
// other units to move to the build position or else they get in the way
// No need to adjust repair pos since we already did this above via: Vec2i buildPos = map->findBestBuildApproach(unit->getPos(), command->getPos(), peerUnitBuilder->getCurrCommand()->getUnitType());
//repairPos = command->getPos()-Vec2i(1);
}
//if not repairing
if(startRepairing == true) {
if(SystemFlags::getSystemSettingType(SystemFlags::debugUnitCommands).enabled) SystemFlags::OutputDebug(SystemFlags::debugUnitCommands,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
if(nextToRepaired == true) {
if(SystemFlags::getSystemSettingType(SystemFlags::debugUnitCommands).enabled) SystemFlags::OutputDebug(SystemFlags::debugUnitCommands,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
unit->setTarget(repaired);
unit->setCurrSkill(rct->getRepairSkillType());
}
else {
if(SystemFlags::getSystemSettingType(SystemFlags::debugUnitCommands).enabled) SystemFlags::OutputDebug(SystemFlags::debugUnitCommands,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
if(SystemFlags::getSystemSettingType(SystemFlags::debugWorldSynch).enabled == true && frameIndex < 0) {
char szBuf[8096]="";
snprintf(szBuf,8096,"[updateRepair] unit->getPos() [%s] command->getPos()() [%s] repairPos [%s]",unit->getPos().getString().c_str(),command->getPos().getString().c_str(),repairPos.getString().c_str());
unit->logSynchData(__FILE__,__LINE__,szBuf);
}
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());
// If the repair command has no move skill and we are not next to
// the unit we cannot repair it
if(rct->getMoveSkillType() == NULL) {
//printf("CANCEL REPAIR NOT NEXT TO REPAIR UNIT\n");
//Vec2i repairPos = command->getPos();
//bool startRepairing = (repaired != NULL && rct->isRepairableUnitType(repaired->getType()) && repaired->isDamaged());
//bool nextToRepaired = repaired != NULL && map->isNextTo(unit, repaired);
//printf("repairPos [%s] startRepairing = %d nextToRepaired = %d unit->getPos() [%s] repaired->getPos() [%s]\n",repairPos.getString().c_str(),startRepairing,nextToRepaired,unit->getPos().getString().c_str(),repaired->getPos().getString().c_str());
console->addStdMessage("InvalidPosition");
unit->setCurrSkill(scStop);
unit->finishCommand();
}
else {
TravelState ts;
switch(this->game->getGameSettings()->getPathFinderType()) {
case pfBasic:
if(SystemFlags::getSystemSettingType(SystemFlags::debugUnitCommands).enabled) SystemFlags::OutputDebug(SystemFlags::debugUnitCommands,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
ts = pathFinder->findPath(unit, repairPos, NULL, frameIndex);
break;
default:
throw megaglest_runtime_error("detected unsupported pathfinder type!");
}
if(SystemFlags::getSystemSettingType(SystemFlags::debugUnitCommands).enabled) SystemFlags::OutputDebug(SystemFlags::debugUnitCommands,"In [%s::%s Line: %d] ts = %d\n",__FILE__,__FUNCTION__,__LINE__,ts);
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());
switch(ts) {
case tsMoving:
if(SystemFlags::getSystemSettingType(SystemFlags::debugUnitCommands).enabled) SystemFlags::OutputDebug(SystemFlags::debugUnitCommands,"In [%s::%s Line: %d] tsMoving\n",__FILE__,__FUNCTION__,__LINE__);
unit->setCurrSkill(rct->getMoveSkillType());
break;
case tsBlocked:
if(SystemFlags::getSystemSettingType(SystemFlags::debugUnitCommands).enabled) SystemFlags::OutputDebug(SystemFlags::debugUnitCommands,"In [%s::%s Line: %d] tsBlocked\n",__FILE__,__FUNCTION__,__LINE__);
if(unit->getPath()->isBlocked()) {
if(SystemFlags::getSystemSettingType(SystemFlags::debugUnitCommands).enabled) SystemFlags::OutputDebug(SystemFlags::debugUnitCommands,"In [%s::%s Line: %d] about to call [scStop]\n",__FILE__,__FUNCTION__,__LINE__);
if(unit->getRetryCurrCommandCount() > 0) {
if(SystemFlags::getSystemSettingType(SystemFlags::debugUnitCommands).enabled) SystemFlags::OutputDebug(SystemFlags::debugUnitCommands,"In [%s::%s Line: %d] will retry command, unit->getRetryCurrCommandCount() = %d\n",__FILE__,__FUNCTION__,__LINE__,unit->getRetryCurrCommandCount());
unit->setRetryCurrCommandCount(0);
unit->getPath()->clear();
updateUnitCommand(unit,-1);
}
else {
unit->finishCommand();
}
}
break;
default:
break;
}
}
}
}
else {
if(SystemFlags::getSystemSettingType(SystemFlags::debugUnitCommands).enabled) SystemFlags::OutputDebug(SystemFlags::debugUnitCommands,"In [%s::%s Line: %d] about to call [scStop]\n",__FILE__,__FUNCTION__,__LINE__);
//console->addStdMessage("InvalidPosition");
unit->setCurrSkill(scStop);
unit->finishCommand();
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());
}
}
else {
if(SystemFlags::getSystemSettingType(SystemFlags::debugUnitCommands).enabled) SystemFlags::OutputDebug(SystemFlags::debugUnitCommands,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
bool cancelRepair = false;
//if repairing
if(repaired != NULL) {
if(SystemFlags::getSystemSettingType(SystemFlags::debugUnitCommands).enabled) SystemFlags::OutputDebug(SystemFlags::debugUnitCommands,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
// Check if we can still repair the unit (may have morphed, etc)
bool canStillRepair = rct->isRepairableUnitType(repaired->getType());
if(canStillRepair == true) {
unit->setTarget(repaired);
}
else {
//printf("CANCELLING CURRENT REPAIR, unit [%s - %d] for unit [%s - %d]\n",unit->getType()->getName().c_str(),unit->getId(),repaired->getType()->getName().c_str(),repaired->getId());
// for(unsigned int i = 0; i < rct->getRepairCount(); ++i) {
// const UnitType *rUnit = rct->getRepair(i);
// printf("Can repair unittype [%s]\n",rUnit->getName().c_str());
// }
unit->setCurrSkill(scStop);
unit->finishCommand();
cancelRepair = true;
}
}
else if(peerUnitBuilder != NULL) {
if(SystemFlags::getSystemSettingType(SystemFlags::debugUnitCommands).enabled) SystemFlags::OutputDebug(SystemFlags::debugUnitCommands,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
unit->setTargetPos(command->getPos());
}
if(cancelRepair == false && (repaired == NULL || repaired->repair()) &&
peerUnitBuilder == NULL) {
if(SystemFlags::getSystemSettingType(SystemFlags::debugUnitCommands).enabled) SystemFlags::OutputDebug(SystemFlags::debugUnitCommands,"In [%s::%s Line: %d] about to call [scStop]\n",__FILE__,__FUNCTION__,__LINE__);
unit->setCurrSkill(scStop);
unit->finishCommand();
if(repaired != NULL && repaired->isBuilt() == false) {
if(SystemFlags::getSystemSettingType(SystemFlags::debugUnitCommands).enabled) SystemFlags::OutputDebug(SystemFlags::debugUnitCommands,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
repaired->born(ct);
scriptManager->onUnitCreated(repaired);
}
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());
}
}
if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s] Line: %d took msecs: %lld --------------------------- [END OF METHOD] ---------------------------\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis());
}
catch(const exception &ex) {
//setRunningStatus(false);
SystemFlags::OutputDebug(SystemFlags::debugError,"In [%s::%s Line: %d] Error [%s]\n",__FILE__,__FUNCTION__,__LINE__,ex.what());
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
throw megaglest_runtime_error(ex.what());
}
catch(...) {
char szBuf[8096]="";
snprintf(szBuf,8096,"In [%s::%s %d] UNKNOWN error\n",__FILE__,__FUNCTION__,__LINE__);
SystemFlags::OutputDebug(SystemFlags::debugError,szBuf);
throw megaglest_runtime_error(szBuf);
}
}
// ==================== updateProduce ====================
void UnitUpdater::updateProduce(Unit *unit, int frameIndex) {
try {
// Nothing to do
if(frameIndex >= 0) {
clearUnitPrecache(unit);
return;
}
if(SystemFlags::getSystemSettingType(SystemFlags::debugWorldSynch).enabled == true && frameIndex < 0) {
char szBuf[8096]="";
snprintf(szBuf,8096,"[updateProduce]");
unit->logSynchData(extractFileFromDirectoryPath(__FILE__).c_str(),__LINE__,szBuf);
}
Chrono chrono;
if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled) chrono.start();
Command *command= unit->getCurrCommand();
if(command == NULL) {
throw megaglest_runtime_error("command == NULL");
}
const ProduceCommandType *pct= static_cast<const ProduceCommandType*>(command->getCommandType());
Unit *produced;
if(unit->getCurrSkill()->getClass() != scProduce) {
//if not producing
unit->setCurrSkill(pct->getProduceSkillType());
}
else {
const CommandType *ct = (command != NULL ? command->getCommandType() : NULL);
unit->update2();
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());
if(unit->getProgress2() > pct->getProduced()->getProductionTime()){
unit->finishCommand();
unit->setCurrSkill(scStop);
UnitPathInterface *newpath = NULL;
switch(this->game->getGameSettings()->getPathFinderType()) {
case pfBasic:
newpath = new UnitPathBasic();
break;
default:
throw megaglest_runtime_error("detected unsupported pathfinder type!");
}
produced= new Unit(world->getNextUnitId(unit->getFaction()), newpath, Vec2i(0), pct->getProducedUnit(), unit->getFaction(), world->getMap(), CardinalDir::NORTH);
if(SystemFlags::getSystemSettingType(SystemFlags::debugUnitCommands).enabled) SystemFlags::OutputDebug(SystemFlags::debugUnitCommands,"In [%s::%s Line: %d] about to place unit for unit [%s]\n",__FILE__,__FUNCTION__,__LINE__,produced->toString(false).c_str());
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());
//place unit creates the unit
if(!world->placeUnit(unit->getCenteredPos(), 10, produced)) {
if(SystemFlags::getSystemSettingType(SystemFlags::debugUnitCommands).enabled) SystemFlags::OutputDebug(SystemFlags::debugUnitCommands,"In [%s::%s Line: %d] COULD NOT PLACE UNIT for unitID [%d]\n",__FILE__,__FUNCTION__,__LINE__,produced->getId());
delete produced;
}
else{
produced->create();
produced->born(ct);
world->getStats()->produce(unit->getFactionIndex(),produced->getType()->getCountUnitProductionInStats());
const CommandType *ct= produced->computeCommandType(unit->getMeetingPos());
if(ct != NULL) {
if(SystemFlags::getSystemSettingType(SystemFlags::debugUnitCommands).enabled) SystemFlags::OutputDebug(SystemFlags::debugUnitCommands,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
produced->giveCommand(new Command(ct, unit->getMeetingPos()));
}
scriptManager->onUnitCreated(produced);
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());
}
}
}
if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s] Line: %d took msecs: %lld --------------------------- [END OF METHOD] ---------------------------\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis());
}
catch(const exception &ex) {
//setRunningStatus(false);
SystemFlags::OutputDebug(SystemFlags::debugError,"In [%s::%s Line: %d] Error [%s]\n",__FILE__,__FUNCTION__,__LINE__,ex.what());
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
throw megaglest_runtime_error(ex.what());
}
catch(...) {
char szBuf[8096]="";
snprintf(szBuf,8096,"In [%s::%s %d] UNKNOWN\n",__FILE__,__FUNCTION__,__LINE__);
SystemFlags::OutputDebug(SystemFlags::debugError,szBuf);
throw megaglest_runtime_error(szBuf);
}
}
// ==================== updateUpgrade ====================
void UnitUpdater::updateUpgrade(Unit *unit, int frameIndex) {
try {
// Nothing to do
if(frameIndex >= 0) {
clearUnitPrecache(unit);
return;
}
if(SystemFlags::getSystemSettingType(SystemFlags::debugWorldSynch).enabled == true && frameIndex < 0) {
char szBuf[8096]="";
snprintf(szBuf,8096,"[updateUpgrade]");
unit->logSynchData(extractFileFromDirectoryPath(__FILE__).c_str(),__LINE__,szBuf);
}
Chrono chrono;
if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled) chrono.start();
Command *command= unit->getCurrCommand();
if(command == NULL) {
throw megaglest_runtime_error("command == NULL");
}
const UpgradeCommandType *uct= static_cast<const UpgradeCommandType*>(command->getCommandType());
if(unit->getCurrSkill()->getClass() != scUpgrade) {
//if not producing
unit->setCurrSkill(uct->getUpgradeSkillType());
}
else {
//if producing
unit->update2();
if(unit->getProgress2() > uct->getProduced()->getProductionTime()){
unit->finishCommand();
unit->setCurrSkill(scStop);
unit->getFaction()->finishUpgrade(uct->getProducedUpgrade());
}
}
if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s] Line: %d took msecs: %lld --------------------------- [END OF METHOD] ---------------------------\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis());
}
catch(const exception &ex) {
//setRunningStatus(false);
SystemFlags::OutputDebug(SystemFlags::debugError,"In [%s::%s Line: %d] Error [%s]\n",__FILE__,__FUNCTION__,__LINE__,ex.what());
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
throw megaglest_runtime_error(ex.what());
}
catch(...) {
char szBuf[8096]="";
snprintf(szBuf,8096,"In [%s::%s %d] UNKNOWN error\n",__FILE__,__FUNCTION__,__LINE__);
SystemFlags::OutputDebug(SystemFlags::debugError,szBuf);
throw megaglest_runtime_error(szBuf);
}
}
// ==================== updateMorph ====================
void UnitUpdater::updateMorph(Unit *unit, int frameIndex) {
try {
// Nothing to do
if(frameIndex >= 0) {
clearUnitPrecache(unit);
return;
}
if(SystemFlags::getSystemSettingType(SystemFlags::debugWorldSynch).enabled == true && frameIndex < 0) {
char szBuf[8096]="";
snprintf(szBuf,8096,"[updateMorph]");
unit->logSynchData(extractFileFromDirectoryPath(__FILE__).c_str(),__LINE__,szBuf);
}
Chrono chrono;
if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled) chrono.start();
Command *command= unit->getCurrCommand();
if(command == NULL) {
throw megaglest_runtime_error("command == NULL");
}
const MorphCommandType *mct= static_cast<const MorphCommandType*>(command->getCommandType());
if(unit->getCurrSkill()->getClass()!=scMorph){
//if not morphing, check space
if(map->isFreeCellsOrHasUnit(unit->getPos(), mct->getMorphUnit()->getSize(), mct->getMorphUnit()->getField(), unit, mct->getMorphUnit())){
unit->setCurrSkill(mct->getMorphSkillType());
// block space for morphing units ( block space before and after morph ! )
map->putUnitCells(unit, unit->getPos());
}
else{
if(unit->getFactionIndex()==world->getThisFactionIndex()){
console->addStdMessage("InvalidPosition");
}
unit->cancelCommand();
}
}
else{
unit->update2();
if(unit->getProgress2() > mct->getProduced()->getProductionTime()){
//int oldSize = 0;
//bool needMapUpdate = false;
switch(this->game->getGameSettings()->getPathFinderType()) {
case pfBasic:
break;
default:
throw megaglest_runtime_error("detected unsupported pathfinder type!");
}
//finish the command
if(unit->morph(mct)){
unit->finishCommand();
if(gui->isSelected(unit)){
gui->onSelectionChanged();
}
switch(this->game->getGameSettings()->getPathFinderType()) {
case pfBasic:
break;
default:
throw megaglest_runtime_error("detected unsupported pathfinder type!");
}
scriptManager->onUnitCreated(unit);
}
else{
unit->cancelCommand();
if(unit->getFactionIndex()==world->getThisFactionIndex()){
console->addStdMessage("InvalidPosition");
}
}
unit->setCurrSkill(scStop);
}
}
if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s] Line: %d took msecs: %lld --------------------------- [END OF METHOD] ---------------------------\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis());
}
catch(const exception &ex) {
//setRunningStatus(false);
SystemFlags::OutputDebug(SystemFlags::debugError,"In [%s::%s Line: %d] Error [%s]\n",__FILE__,__FUNCTION__,__LINE__,ex.what());
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
throw megaglest_runtime_error(ex.what());
}
catch(...) {
char szBuf[8096]="";
snprintf(szBuf,8096,"In [%s::%s %d] UNKNOWN error\n",__FILE__,__FUNCTION__,__LINE__);
SystemFlags::OutputDebug(SystemFlags::debugError,szBuf);
throw megaglest_runtime_error(szBuf);
}
}
// ==================== updateMove ====================
void UnitUpdater::updateSwitchTeam(Unit *unit, int frameIndex) {
}
// ==================== updateAttack ====================
// ==================== PRIVATE ====================
// ==================== attack ====================
void UnitUpdater::hit(Unit *attacker){
hit(attacker, dynamic_cast<const AttackSkillType*>(attacker->getCurrSkill()), attacker->getTargetPos(), attacker->getTargetField());
}
void UnitUpdater::hit(Unit *attacker, const AttackSkillType* ast, const Vec2i &targetPos, Field targetField){
//hit attack positions
if(ast != NULL && ast->getSplash()) {
char szBuf[8096]="";
snprintf(szBuf,8095,"Unit hitting [UnitUpdater::hit] hasSplash = %d radius = %d damageall = %d",ast->getSplash(),ast->getSplashRadius(),ast->getSplashDamageAll());
attacker->addNetworkCRCDecHp(szBuf);
PosCircularIterator pci(map, targetPos, ast->getSplashRadius());
while(pci.next()) {
Unit *attacked= map->getCell(pci.getPos())->getUnit(targetField);
if(attacked != NULL) {
if(ast->getSplashDamageAll() ||
attacker->isAlly(attacked) == false ||
( targetPos.x == pci.getPos().x && targetPos.y == pci.getPos().y )) {
attacker->setLastAttackedUnitId(attacked->getId());
scriptManager->onUnitAttacking(attacker);
float distance = pci.getPos().dist(targetPos);
distance = truncateDecimal<float>(distance,6);
damage(attacker, ast, attacked, distance);
}
}
}
}
else {
Unit *attacked= map->getCell(targetPos)->getUnit(targetField);
char szBuf[8096]="";
snprintf(szBuf,8095,"Unit hitting [UnitUpdater::hit 2] attacked = %d",(attacked != NULL ? attacked->getId() : -1));
attacker->addNetworkCRCDecHp(szBuf);
if(attacked != NULL) {
damage(attacker, ast, attacked, 0.f);
}
}
}
void UnitUpdater::damage(Unit *attacker, const AttackSkillType* ast, Unit *attacked, float distance) {
if(attacker == NULL) {
throw megaglest_runtime_error("attacker == NULL");
}
if(ast == NULL) {
throw megaglest_runtime_error("ast == NULL");
}
if(attacked == NULL) {
throw megaglest_runtime_error("attacked == NULL");
}
//get vars
float damage = ast->getTotalAttackStrength(attacker->getTotalUpgrade());
int var = ast->getAttackVar();
int armor = attacked->getType()->getTotalArmor(attacked->getTotalUpgrade());
float damageMultiplier = world->getTechTree()->getDamageMultiplier(ast->getAttackType(), attacked->getType()->getArmorType());
damageMultiplier = truncateDecimal<float>(damageMultiplier,6);
//compute damage
//damage += random.randRange(-var, var);
damage += attacker->getRandom()->randRange(-var, var, extractFileFromDirectoryPath(__FILE__) + intToStr(__LINE__));
damage /= distance+1;
damage -= armor;
damage *= damageMultiplier;
damage = truncateDecimal<float>(damage,6);
if(damage < 1) {
damage= 1;
}
int damageVal = static_cast<int>(damage);
attacked->setLastAttackerUnitId(attacker->getId());
char szBuf[8096]="";
snprintf(szBuf,8095,"Unit hitting [UnitUpdater::damage] damageVal = %d",damageVal);
attacker->addNetworkCRCDecHp(szBuf);
//damage the unit
if(attacked->decHp(damageVal)) {
world->getStats()->kill(attacker->getFactionIndex(), attacked->getFactionIndex(), attacker->getTeam() != attacked->getTeam(),attacked->getType()->getCountUnitDeathInStats(),attacked->getType()->getCountUnitKillInStats());
if(attacked->getType()->getCountKillForUnitUpgrade() == true){
attacker->incKills(attacked->getTeam());
}
int lootableResourceCount = attacked->getType()->getLootableResourceCount();
for(int i = 0; i < lootableResourceCount; i++) {
LootableResource resource = attacked->getType()->getLootableResource(i);
// Figure out how much of the resource in question that the attacked unit's faction has
int factionTotalResource = 0;
for(int j = 0; j < attacked->getFaction()->getTechTree()->getResourceTypeCount(); j++) {
if(attacked->getFaction()->getTechTree()->getResourceType(j) == resource.getResourceType()) {
factionTotalResource = attacked->getFaction()->getResource(j)->getAmount();
break;
}
}
if(resource.isNegativeAllowed()) {
attacked->getFaction()->incResourceAmount(resource.getResourceType(), -resource.getLossPercentage() * factionTotalResource);
attacked->getFaction()->incResourceAmount(resource.getResourceType(), -resource.getLossValue());
attacker->getFaction()->incResourceAmount(resource.getResourceType(), resource.getAmountPercentage() * factionTotalResource);
attacker->getFaction()->incResourceAmount(resource.getResourceType(), resource.getAmountValue());
}
// Can't take more resources than the faction has, otherwise we end up in the negatives
else {
attacked->getFaction()->incResourceAmount(resource.getResourceType(), -min(resource.getLossPercentage() * factionTotalResource, factionTotalResource));
attacked->getFaction()->incResourceAmount(resource.getResourceType(), -min(resource.getLossValue(), factionTotalResource));
attacker->getFaction()->incResourceAmount(resource.getResourceType(), min(resource.getAmountPercentage() * factionTotalResource, factionTotalResource));
attacker->getFaction()->incResourceAmount(resource.getResourceType(), min(resource.getAmountValue(), factionTotalResource));
}
}
switch(this->game->getGameSettings()->getPathFinderType()) {
case pfBasic:
break;
default:
throw megaglest_runtime_error("detected unsupported pathfinder type!");
}
attacked->setCauseOfDeath(ucodAttacked);
scriptManager->onUnitDied(attacked);
}
if(attacked->isAlive() == true) {
scriptManager->onUnitAttacked(attacked);
}
// !!! Is this causing choppy network play somehow?
//attacker->computeHp();
}
void UnitUpdater::startAttackParticleSystem(Unit *unit){
Renderer &renderer= Renderer::getInstance();
ProjectileParticleSystem *psProj = 0;
const AttackSkillType *ast= dynamic_cast<const AttackSkillType*>(unit->getCurrSkill());
if(ast == NULL) {
throw megaglest_runtime_error("Start attack particle ast == NULL!");
}
ParticleSystemTypeProjectile *pstProj= ast->getProjParticleType();
ParticleSystemTypeSplash *pstSplash= ast->getSplashParticleType();
Vec3f startPos= unit->getCurrVector();
Vec3f endPos= unit->getTargetVec();
//make particle system
const SurfaceCell *sc= map->getSurfaceCell(Map::toSurfCoords(unit->getPos()));
const SurfaceCell *tsc= map->getSurfaceCell(Map::toSurfCoords(unit->getTargetPos()));
bool visible= sc->isVisible(world->getThisTeamIndex()) || tsc->isVisible(world->getThisTeamIndex());
if(visible == false && world->showWorldForPlayer(world->getThisFactionIndex()) == true) {
visible = true;
}
//projectile
if(pstProj != NULL) {
psProj= pstProj->create(unit);
psProj->setPath(startPos, endPos);
psProj->setObserver(new ParticleDamager(unit, this, gameCamera));
psProj->setVisible(visible);
if(unit->getFaction()->getTexture()) {
psProj->setFactionColor(unit->getFaction()->getTexture()->getPixmapConst()->getPixel3f(0,0));
}
renderer.manageParticleSystem(psProj, rsGame);
unit->addAttackParticleSystem(psProj);
}
else {
char szBuf[8096]="";
snprintf(szBuf,8095,"Unit hitting [startAttackParticleSystem] no proj");
unit->addNetworkCRCDecHp(szBuf);
hit(unit);
}
//splash
if(pstSplash != NULL) {
SplashParticleSystem *psSplash= pstSplash->create(unit);
psSplash->setPos(endPos);
psSplash->setVisible(visible);
if(unit->getFaction()->getTexture()) {
psSplash->setFactionColor(unit->getFaction()->getTexture()->getPixmapConst()->getPixel3f(0,0));
}
renderer.manageParticleSystem(psSplash, rsGame);
if(pstProj!=NULL){
psProj->link(psSplash);
}
unit->addAttackParticleSystem(psSplash);
}
}
// ==================== misc ====================
//looks for a resource of type rt, if rt==NULL looks for any
//resource the unit can harvest
bool UnitUpdater::searchForResource(Unit *unit, const HarvestCommandType *hct) {
Vec2i pos= unit->getCurrCommand()->getPos();
for(int radius= 0; radius < maxResSearchRadius; radius++) {
for(int i = pos.x - radius; i <= pos.x + radius; ++i) {
for(int j=pos.y - radius; j <= pos.y + radius; ++j) {
if(map->isInside(i, j)) {
Resource *r= map->getSurfaceCell(Map::toSurfCoords(Vec2i(i, j)))->getResource();
if(r != NULL) {
if(hct->canHarvest(r->getType())) {
const Vec2i newPos = Vec2i(i, j);
if(unit->isBadHarvestPos(newPos) == false) {
unit->getCurrCommand()->setPos(newPos);
return true;
}
}
}
}
}
}
}
return false;
}
bool UnitUpdater::attackerOnSight(Unit *unit, Unit **rangedPtr, bool evalMode){
int range= unit->getType()->getSight();
return unitOnRange(unit, range, rangedPtr, NULL,evalMode);
}
bool UnitUpdater::attackableOnSight(Unit *unit, Unit **rangedPtr, const AttackSkillType *ast, bool evalMode) {
int range= unit->getType()->getSight();
return unitOnRange(unit, range, rangedPtr, ast, evalMode);
}
bool UnitUpdater::attackableOnRange(Unit *unit, Unit **rangedPtr, const AttackSkillType *ast,bool evalMode) {
int range= ast->getTotalAttackRange(unit->getTotalUpgrade());
return unitOnRange(unit, range, rangedPtr, ast, evalMode);
}
bool UnitUpdater::findCachedCellsEnemies(Vec2i center, int range, int size, vector<Unit*> &enemies,
const AttackSkillType *ast, const Unit *unit,
const Unit *commandTarget) {
bool result = false;
MutexSafeWrapper safeMutex(mutexUnitRangeCellsLookupItemCache,string(__FILE__) + "_" + intToStr(__LINE__));
std::map<Vec2i, std::map<int, std::map<int, UnitRangeCellsLookupItem > > >::iterator iterFind = UnitRangeCellsLookupItemCache.find(center);
if(iterFind != UnitRangeCellsLookupItemCache.end()) {
std::map<int, std::map<int, UnitRangeCellsLookupItem > >::iterator iterFind3 = iterFind->second.find(size);
if(iterFind3 != iterFind->second.end()) {
std::map<int, UnitRangeCellsLookupItem>::iterator iterFind4 = iterFind3->second.find(range);
if(iterFind4 != iterFind3->second.end()) {
result = true;
std::vector<Cell *> &cellList = iterFind4->second.rangeCellList;
for(int idx = 0; idx < (int)cellList.size(); ++idx) {
Cell *cell = cellList[idx];
findEnemiesForCell(ast,cell,unit,commandTarget,enemies);
}
}
}
}
return result;
}
void UnitUpdater::findEnemiesForCell(const AttackSkillType *ast, Cell *cell, const Unit *unit,
const Unit *commandTarget,vector<Unit*> &enemies) {
//all fields
for(int k = 0; k < fieldCount; k++) {
Field f= static_cast<Field>(k);
//check field
if((ast == NULL || ast->getAttackField(f))) {
Unit *possibleEnemy = cell->getUnit(f);
//check enemy
if(possibleEnemy != NULL && possibleEnemy->isAlive()) {
if((unit->isAlly(possibleEnemy) == false && commandTarget == NULL) ||
commandTarget == possibleEnemy) {
enemies.push_back(possibleEnemy);
}
}
}
}
}
void UnitUpdater::findEnemiesForCell(const Vec2i pos, int size, int sightRange, const Faction *faction, vector<Unit*> &enemies, bool attackersOnly) const {
//all fields
for(int k = 0; k < fieldCount; k++) {
Field f= static_cast<Field>(k);
for(int i = pos.x - sightRange; i < pos.x + size + sightRange; ++i) {
for(int j = pos.y - sightRange; j < pos.y + size + sightRange; ++j) {
Vec2i testPos(i,j);
if( map->isInside(testPos) &&
map->isInsideSurface(map->toSurfCoords(testPos))) {
Cell *cell = map->getCell(testPos);
//check field
Unit *possibleEnemy = cell->getUnit(f);
//check enemy
if(possibleEnemy != NULL && possibleEnemy->isAlive()) {
if(faction->getTeam() != possibleEnemy->getTeam()) {
if(attackersOnly == true) {
if(possibleEnemy->getType()->hasCommandClass(ccAttack) || possibleEnemy->getType()->hasCommandClass(ccAttackStopped)) {
enemies.push_back(possibleEnemy);
}
}
else {
enemies.push_back(possibleEnemy);
}
}
}
}
}
}
}
}
//if the unit has any enemy on range
bool UnitUpdater::unitOnRange(Unit *unit, int range, Unit **rangedPtr,
const AttackSkillType *ast,bool evalMode) {
bool result=false;
try {
vector<Unit*> enemies;
enemies.reserve(100);
//we check command target
const Unit *commandTarget = NULL;
if(unit->anyCommand() && unit->getCurrCommand() != NULL) {
commandTarget = static_cast<const Unit*>(unit->getCurrCommand()->getUnit());
}
if(commandTarget != NULL && commandTarget->isDead()) {
commandTarget = NULL;
}
//aux vars
int size = unit->getType()->getSize();
Vec2i center = unit->getPos();
Vec2f floatCenter = unit->getFloatCenteredPos();
//bool foundInCache = true;
if(findCachedCellsEnemies(center,range,size,enemies,ast,
unit,commandTarget) == false) {
//foundInCache = false;
//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(static_cast<streflop::Simple>(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);
findEnemiesForCell(ast,cell,unit,commandTarget,enemies);
cacheItem.rangeCellList.push_back(cell);
}
}
}
// Ok update our caches with the latest info
if(cacheItem.rangeCellList.empty() == false) {
MutexSafeWrapper safeMutex(mutexUnitRangeCellsLookupItemCache,string(__FILE__) + "_" + intToStr(__LINE__));
UnitRangeCellsLookupItemCache[center][size][range] = cacheItem;
}
}
//attack enemies that can attack first
float distToUnit= -1;
Unit* enemySeen= NULL;
float distToStandingUnit= -1;
Unit* attackingEnemySeen= NULL;
ControlType controlType= unit->getFaction()->getControlType();
bool isUltra= controlType == ctCpuUltra || controlType == ctNetworkCpuUltra;
bool isMega= controlType == ctCpuMega || controlType == ctNetworkCpuMega;
string randomInfoData = "enemies.size() = " + intToStr(enemies.size());
//printf("unit %d has control:%d\n",unit->getId(),controlType);
for(int i = 0; i< (int)enemies.size(); ++i) {
Unit *enemy = enemies[i];
if(enemy != NULL && enemy->isAlive() == true) {
// Here we default to first enemy if no attackers found
if(enemySeen == NULL) {
*rangedPtr = enemy;
enemySeen = enemy;
result = true;
}
//randomInfoData += " i = " + intToStr(i) + " alive = true result = " + intToStr(result);
// Attackers get first priority
if(enemy->getType()->hasSkillClass(scAttack) == true) {
float currentDist = unit->getCenteredPos().dist(enemy->getCenteredPos());
//randomInfoData += " currentDist = " + floatToStr(currentDist);
// Select closest attacking unit
if(distToUnit < 0 || currentDist< distToUnit) {
distToUnit = currentDist;
*rangedPtr = enemies[i];
enemySeen = enemies[i];
result = true;
}
if(isUltra || isMega) {
if(distToStandingUnit < 0 || currentDist< distToStandingUnit) {
if(enemies[i]->getCurrSkill()!=NULL && enemies[i]->getCurrSkill()->getClass()==scAttack) {
distToStandingUnit = currentDist;
attackingEnemySeen=enemies[i];
}
}
}
}
}
}
if(evalMode == false && (isUltra || isMega)) {
unit->getRandom()->addLastCaller(randomInfoData);
if( attackingEnemySeen!=NULL && unit->getRandom()->randRange(0,2,extractFileFromDirectoryPath(__FILE__) + intToStr(__LINE__)) != 2 ) {
*rangedPtr = attackingEnemySeen;
enemySeen = attackingEnemySeen;
//printf("Da hat er wen gefunden:%s\n",enemySeen->getType()->getName(false).c_str());
}
}
if(result == true) {
//const Unit* teamUnit = NULL;
const Unit* enemyUnit = NULL;
bool onlyEnemyUnits = true;
if(unit->getTeam() == world->getThisTeamIndex()) {
//teamUnit = unit;
enemyUnit = enemySeen;
onlyEnemyUnits = false;
}
else if(enemySeen->getTeam() == world->getThisTeamIndex()) {
//teamUnit = enemySeen;
enemyUnit = unit;
onlyEnemyUnits = false;
}
if(evalMode == false && onlyEnemyUnits == false &&
enemyUnit->getTeam() != world->getThisTeamIndex()) {
Vec2f enemyFloatCenter = enemyUnit->getFloatCenteredPos();
// find nearest Attack and cleanup old dates
AttackWarningData *nearest = NULL;
float currentDistance = 0.f;
float nearestDistance = 0.f;
MutexSafeWrapper safeMutex(mutexAttackWarnings,string(__FILE__) + "_" + intToStr(__LINE__));
for(int i = (int)attackWarnings.size() - 1; i >= 0; --i) {
if(world->getFrameCount() - attackWarnings[i]->lastFrameCount > 200) { //after 200 frames attack break we warn again
AttackWarningData *toDelete =attackWarnings[i];
attackWarnings.erase(attackWarnings.begin()+i);
delete toDelete; // old one
}
else {
#ifdef USE_STREFLOP
currentDistance = streflop::floor(static_cast<streflop::Simple>(enemyFloatCenter.dist(attackWarnings[i]->attackPosition))); // no need for streflops here!
#else
currentDistance = floor(enemyFloatCenter.dist(attackWarnings[i]->attackPosition)); // no need for streflops here!
#endif
if(nearest == NULL) {
nearest = attackWarnings[i];
nearestDistance = currentDistance;
}
else {
if(currentDistance < nearestDistance) {
nearest = attackWarnings[i];
nearestDistance = currentDistance;
}
}
}
}
if(nearest != NULL) {
// does it fit?
if(nearestDistance < attackWarnRange) {
// update entry with current values
nearest->lastFrameCount=world->getFrameCount();
nearest->attackPosition.x=enemyFloatCenter.x;
nearest->attackPosition.y=enemyFloatCenter.y;
}
else {
//Must be a different Attack!
nearest=NULL; //set to null to force a new entry in next step
}
}
// add new attack
if(nearest == NULL) {
// no else!
AttackWarningData* awd= new AttackWarningData();
awd->lastFrameCount=world->getFrameCount();
awd->attackPosition.x=enemyFloatCenter.x;
awd->attackPosition.y=enemyFloatCenter.y;
MutexSafeWrapper safeMutex(mutexAttackWarnings,string(__FILE__) + "_" + intToStr(__LINE__));
attackWarnings.push_back(awd);
if(world->getAttackWarningsEnabled() == true) {
SoundRenderer::getInstance().playFx(CoreData::getInstance().getAttentionSound());
world->addAttackEffects(enemyUnit);
}
}
}
}
}
catch(const exception &ex) {
//setRunningStatus(false);
SystemFlags::OutputDebug(SystemFlags::debugError,"In [%s::%s Line: %d] Error [%s]\n",__FILE__,__FUNCTION__,__LINE__,ex.what());
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
throw megaglest_runtime_error(ex.what());
}
catch(...) {
char szBuf[8096]="";
snprintf(szBuf,8096,"In [%s::%s %d] UNKNOWN error\n",__FILE__,__FUNCTION__,__LINE__);
SystemFlags::OutputDebug(SystemFlags::debugError,szBuf);
throw megaglest_runtime_error(szBuf);
}
return result;
}
//if the unit has any enemy on range
vector<Unit*> UnitUpdater::enemyUnitsOnRange(const Unit *unit,const AttackSkillType *ast) {
vector<Unit*> enemies;
enemies.reserve(100);
try {
int range = unit->getType()->getSight();
if(ast != NULL) {
range = ast->getTotalAttackRange(unit->getTotalUpgrade());
}
//we check command target
const Unit *commandTarget = NULL;
// if(unit->anyCommand()) {
// commandTarget = static_cast<const Unit*>(unit->getCurrCommand()->getUnit());
// }
// if(commandTarget != NULL && commandTarget->isDead()) {
// commandTarget = NULL;
// }
//aux vars
int size = unit->getType()->getSize();
Vec2i center = unit->getPosNotThreadSafe();
Vec2f floatCenter = unit->getFloatCenteredPos();
//bool foundInCache = true;
if(findCachedCellsEnemies(center,range,size,enemies,ast,
unit,commandTarget) == false) {
//foundInCache = false;
//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(static_cast<streflop::Simple>(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);
findEnemiesForCell(ast,cell,unit,commandTarget,enemies);
cacheItem.rangeCellList.push_back(cell);
}
}
}
// Ok update our caches with the latest info
if(cacheItem.rangeCellList.empty() == false) {
MutexSafeWrapper safeMutex(mutexUnitRangeCellsLookupItemCache,string(__FILE__) + "_" + intToStr(__LINE__));
UnitRangeCellsLookupItemCache[center][size][range] = cacheItem;
}
}
}
catch(const exception &ex) {
//setRunningStatus(false);
SystemFlags::OutputDebug(SystemFlags::debugError,"In [%s::%s Line: %d] Error [%s]\n",__FILE__,__FUNCTION__,__LINE__,ex.what());
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
throw megaglest_runtime_error(ex.what());
}
catch(...) {
char szBuf[8096]="";
snprintf(szBuf,8096,"In [%s::%s %d] UNKNOWN error\n",__FILE__,__FUNCTION__,__LINE__);
SystemFlags::OutputDebug(SystemFlags::debugError,szBuf);
throw megaglest_runtime_error(szBuf);
}
return enemies;
}
void UnitUpdater::findUnitsForCell(Cell *cell, const Unit *unit,vector<Unit*> &units) {
//all fields
if(cell != NULL) {
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->getPosNotThreadSafe();
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(static_cast<streflop::Simple>(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;
}
string UnitUpdater::getUnitRangeCellsLookupItemCacheStats() {
string result = "";
int posCount = 0;
int sizeCount = 0;
int rangeCount = 0;
int rangeCountCellCount = 0;
MutexSafeWrapper safeMutex(mutexUnitRangeCellsLookupItemCache,string(__FILE__) + "_" + intToStr(__LINE__));
for(std::map<Vec2i, std::map<int, std::map<int, UnitRangeCellsLookupItem > > >::iterator iterMap1 = UnitRangeCellsLookupItemCache.begin();
iterMap1 != UnitRangeCellsLookupItemCache.end(); ++iterMap1) {
posCount++;
for(std::map<int, std::map<int, UnitRangeCellsLookupItem > >::iterator iterMap2 = iterMap1->second.begin();
iterMap2 != iterMap1->second.end(); ++iterMap2) {
sizeCount++;
for(std::map<int, UnitRangeCellsLookupItem>::iterator iterMap3 = iterMap2->second.begin();
iterMap3 != iterMap2->second.end(); ++iterMap3) {
rangeCount++;
rangeCountCellCount += (int)iterMap3->second.rangeCellList.size();
}
}
}
uint64 totalBytes = rangeCountCellCount * sizeof(Cell *);
totalBytes /= 1000;
char szBuf[8096]="";
snprintf(szBuf,8096,"pos [%d] size [%d] range [%d][%d] total KB: %s",posCount,sizeCount,rangeCount,rangeCountCellCount,formatNumber(totalBytes).c_str());
result = szBuf;
return result;
}
void UnitUpdater::saveGame(XmlNode *rootNode) {
std::map<string,string> mapTagReplacements;
XmlNode *unitupdaterNode = rootNode->addChild("UnitUpdater");
// const GameCamera *gameCamera;
// Gui *gui;
// Map *map;
// World *world;
// Console *console;
// ScriptManager *scriptManager;
// PathFinder *pathFinder;
pathFinder->saveGame(unitupdaterNode);
// Game *game;
// RandomGen random;
//unitupdaterNode->addAttribute("random",intToStr(random.getLastNumber()), mapTagReplacements);
// float attackWarnRange;
unitupdaterNode->addAttribute("attackWarnRange",floatToStr(attackWarnRange,6), mapTagReplacements);
// AttackWarnings attackWarnings;
//
}
void UnitUpdater::clearCaches() {
if(pathFinder != NULL) {
pathFinder->clearCaches();
}
}
void UnitUpdater::loadGame(const XmlNode *rootNode) {
const XmlNode *unitupdaterNode = rootNode->getChild("UnitUpdater");
pathFinder->loadGame(unitupdaterNode);
//random.setLastNumber(unitupdaterNode->getAttribute("random")->getIntValue());
// float attackWarnRange;
attackWarnRange = unitupdaterNode->getAttribute("attackWarnRange")->getFloatValue();
}
// =====================================================
// class ParticleDamager
// =====================================================
ParticleDamager::ParticleDamager(Unit *attacker, UnitUpdater *unitUpdater, const GameCamera *gameCamera){
this->gameCamera= gameCamera;
this->attackerRef= attacker;
this->ast= static_cast<const AttackSkillType*>(attacker->getCurrSkill());
this->targetPos= attacker->getTargetPos();
this->targetField= attacker->getTargetField();
this->unitUpdater= unitUpdater;
}
void ParticleDamager::update(ParticleSystem *particleSystem) {
Unit *attacker= attackerRef.getUnit();
if(attacker != NULL) {
//string auditBeforeHit = particleSystem->toString();
char szBuf[8096]="";
snprintf(szBuf,8095,"Unit hitting [ParticleDamager::update] [%s] targetField = %d",targetPos.getString().c_str(),targetField);
attacker->addNetworkCRCDecHp(szBuf);
unitUpdater->hit(attacker, ast, targetPos, targetField);
//char szBuf[8096]="";
//snprintf(szBuf,8095,"ParticleDamager::update attacker particleSystem before: %s\nafter: %s",auditBeforeHit.c_str(),particleSystem->toString().c_str());
//attacker->setNetworkCRCParticleObserverLogInfo(szBuf);
//play sound
StaticSound *projSound= ast->getProjSound();
if(particleSystem->getVisible() && projSound != NULL) {
SoundRenderer::getInstance().playFx(projSound, attacker->getCurrVector(), gameCamera->getPos());
}
}
particleSystem->setObserver(NULL);
delete this;
}
void ParticleDamager::saveGame(XmlNode *rootNode) {
std::map<string,string> mapTagReplacements;
XmlNode *particleDamagerNode = rootNode->addChild("ParticleDamager");
// UnitReference attackerRef;
attackerRef.saveGame(particleDamagerNode);
// const AttackSkillType* ast;
particleDamagerNode->addAttribute("astName",ast->getName(), mapTagReplacements);
particleDamagerNode->addAttribute("astClass",intToStr(ast->getClass()), mapTagReplacements);
// UnitUpdater *unitUpdater;
// const GameCamera *gameCamera;
// Vec2i targetPos;
particleDamagerNode->addAttribute("targetPos",targetPos.getString(), mapTagReplacements);
// Field targetField;
particleDamagerNode->addAttribute("targetField",intToStr(targetField), mapTagReplacements);
}
void ParticleDamager::loadGame(const XmlNode *rootNode, void *genericData) {
const XmlNode *particleDamagerNode = rootNode->getChild("ParticleDamager");
std::pair<Game *,Unit *> *pairData = (std::pair<Game *,Unit *>*)genericData;
//UnitType *ut, Game *game
attackerRef.loadGame(particleDamagerNode,pairData->first->getWorld());
//random.setLastNumber(particleSystemNode->getAttribute("random")->getIntValue());
// const AttackSkillType* ast;
string astName = particleDamagerNode->getAttribute("astName")->getValue();
SkillClass astClass = static_cast<SkillClass>(particleDamagerNode->getAttribute("astClass")->getIntValue());
ast = dynamic_cast<const AttackSkillType*>(pairData->second->getType()->getSkillType(astName,astClass));
// UnitUpdater *unitUpdater;
unitUpdater = pairData->first->getWorld()->getUnitUpdater();
// const GameCamera *gameCamera;
gameCamera = pairData->first->getGameCamera();
// Vec2i targetPos;
targetPos = Vec2i::strToVec2(particleDamagerNode->getAttribute("targetPos")->getValue());
// Field targetField;
targetField = static_cast<Field>(particleDamagerNode->getAttribute("targetField")->getIntValue());
}
}}//end namespace