resolved conflicts to upstream/develop

This commit is contained in:
filux 2014-09-27 11:19:29 +00:00
commit 9988ea9cbf
42 changed files with 3883 additions and 371 deletions

View File

@ -272,10 +272,11 @@ IF(CMAKE_COMPILER_IS_GNUCXX OR MINGW)
IF(APPLE)
SET(CUSTOM_DATA_INSTALL_PATH "'\\\\'${CMAKE_INSTALL_PREFIX}/${MEGAGLEST_DATA_INSTALL_PATH}\\\\''" CACHE STRING "The FULL installation path for data files (this is build automatically by combining CMAKE_INSTALL_PREFIX and MEGAGLEST_DATA_INSTALL_PATH)")
ELSE()
SET(CUSTOM_DATA_INSTALL_PATH "'\\\"${CMAKE_INSTALL_PREFIX}/${MEGAGLEST_DATA_INSTALL_PATH}\\\"'" CACHE STRING "The FULL installation path for data files (this is build automatically by combining CMAKE_INSTALL_PREFIX and MEGAGLEST_DATA_INSTALL_PATH)")
SET(CUSTOM_DATA_INSTALL_PATH "\"${CMAKE_INSTALL_PREFIX}/${MEGAGLEST_DATA_INSTALL_PATH}\"" CACHE STRING "The FULL installation path for data files (this is build automatically by combining CMAKE_INSTALL_PREFIX and MEGAGLEST_DATA_INSTALL_PATH)")
ENDIF()
ENDIF()
SET(CUSTOM_DATA_INSTALL_PATH_VALUE "-DCUSTOM_DATA_INSTALL_PATH=${CUSTOM_DATA_INSTALL_PATH}")
ADD_DEFINITIONS("-DCUSTOM_DATA_INSTALL_PATH=${CUSTOM_DATA_INSTALL_PATH}")
SET(PKG_DATADIR ${CUSTOM_DATA_INSTALL_PATH_VALUE})
SET(PKG_BINDIR ${MEGAGLEST_BIN_INSTALL_PATH})

@ -1 +1 @@
Subproject commit 7de4b4b6d02ae1933e3964cc02d31aa288d49463
Subproject commit 4f05a0177385ce47eb4cfcf5ce6676f59b290d37

View File

@ -54,11 +54,11 @@ fi
cd $PROJDIR
echo "copying binaries ..."
cp -r lib/* "$RELEASEDIR/lib"
cp *.ico "$RELEASEDIR/"
cp {../shared/,}*.ico "$RELEASEDIR/"
cp *.bmp "$RELEASEDIR/"
cp *.png "$RELEASEDIR/"
cp *.xpm "$RELEASEDIR/"
cp *.ini "$RELEASEDIR/"
cp {../shared/,}*.ini "$RELEASEDIR/"
cp megaglest "$RELEASEDIR/"
cp megaglest_editor "$RELEASEDIR/"
cp megaglest_g3dviewer "$RELEASEDIR/"

View File

@ -148,7 +148,7 @@ case $distribution in
$installcommand
if [ $? != 0 ]; then error_during_installation; exit 1; fi
;;
11.10|12.04|12.10|13.04|13.10)
11.10|12.04|12.10|13.04|13.10|14.04)
installcommand='apt-get install '"$APT_OPTIONS"' build-essential cmake libsdl1.2-dev libalut-dev libgl1-mesa-dev libglu1-mesa-dev libvorbis-dev libwxbase2.8-dev libwxgtk2.8-dev libx11-dev liblua5.1-0-dev libjpeg-dev libpng12-dev libcurl4-gnutls-dev libxml2-dev libircclient-dev libglew-dev libftgl-dev libfribidi-dev libvlc-dev libcppunit-dev'
$installcommand
if [ $? != 0 ]; then error_during_installation; exit 1; fi
@ -167,7 +167,7 @@ case $distribution in
fi
case $release in
13|14|15)
13|14|15|16)
installcommand='apt-get install '"$APT_OPTIONS"' build-essential cmake libsdl1.2-dev libalut-dev libgl1-mesa-dev libglu1-mesa-dev libvorbis-dev libwxbase2.8-dev libwxgtk2.8-dev libx11-dev liblua5.1-0-dev libjpeg-dev libpng12-dev libcurl4-gnutls-dev libxml2-dev libircclient-dev libglew-dev libftgl-dev libfribidi-dev libvlc-dev libcppunit-dev'
$installcommand
if [ $? != 0 ]; then error_during_installation; exit 1; fi
@ -180,7 +180,7 @@ case $distribution in
esac
;;
SuSE|SUSE?LINUX|Opensuse)
SuSE|SUSE?LINUX|Opensuse*|openSUSE*)
case $release in
11.2|11.3|11.4|12.1)
installcommand='zypper install gcc gcc-c++ cmake libSDL-devel MesaGLw-devel freeglut-devel libvorbis-devel wxGTK-devel lua-devel libjpeg-devel libpng14-devel libcurl-devel openal-soft-devel xorg-x11-libX11-devel libxml2-devel libircclient-devel glew-devel ftgl-devel fribidi-devel cppunit-devel'
@ -192,6 +192,11 @@ case $distribution in
$installcommand
if [ $? != 0 ]; then error_during_installation; exit 1; fi
;;
13.1)
installcommand='zypper install gcc gcc-c++ cmake libSDL-devel Mesa-libGL-devel freeglut-devel libvorbis-devel wxGTK-devel lua-devel libjpeg-devel libpng-devel libcurl-devel openal-soft-devel xorg-x11-libX11-devel libxml2-devel libircclient-devel glew-devel ftgl-devel fribidi-devel cppunit-devel'
$installcommand
if [ $? != 0 ]; then error_during_installation; exit 1; fi
;;
*)
installcommand='zypper install gcc gcc-c++ cmake libSDL-devel Mesa-libGL-devel freeglut-devel libvorbis-devel wxGTK-devel lua-devel libjpeg-devel libpng14-devel libcurl-devel openal-soft-devel xorg-x11-libX11-devel libxml2-devel libircclient-devel glew-devel ftgl-devel fribidi-devel cppunit-devel'
unsupported_release

View File

@ -269,6 +269,7 @@
<ClCompile Include="..\..\source\glest_game\types\object_type.cpp" />
<ClCompile Include="..\..\source\glest_game\types\resource_type.cpp" />
<ClCompile Include="..\..\source\glest_game\types\skill_type.cpp" />
<ClCompile Include="..\..\source\glest_game\types\projectile_type.cpp" />
<ClCompile Include="..\..\source\glest_game\types\tech_tree.cpp" />
<ClCompile Include="..\..\source\glest_game\types\unit_type.cpp" />
<ClCompile Include="..\..\source\glest_game\types\upgrade_type.cpp" />
@ -356,6 +357,7 @@
<ClInclude Include="..\..\source\glest_game\types\object_type.h" />
<ClInclude Include="..\..\source\glest_game\types\resource_type.h" />
<ClInclude Include="..\..\source\glest_game\types\skill_type.h" />
<ClInclude Include="..\..\source\glest_game\types\projectile_type.h" />
<ClInclude Include="..\..\source\glest_game\types\tech_tree.h" />
<ClInclude Include="..\..\source\glest_game\types\unit_type.h" />
<ClInclude Include="..\..\source\glest_game\types\upgrade_type.h" />

2
source/.gitignore vendored
View File

@ -1 +1,3 @@
/windows_deps*/
/glest_game/facilities/gitversion.h
/glest_game/site/

2329
source/glest_game/Doxyfile Normal file

File diff suppressed because it is too large Load Diff

View File

@ -531,7 +531,7 @@ bool Ai::findAbleUnit(int *unitIndex, CommandClass ability, bool idleOnly){
*unitIndex= -1;
for(int i=0; i<aiInterface->getMyUnitCount(); ++i){
const Unit *unit= aiInterface->getMyUnit(i);
if(unit->getType()->hasCommandClass(ability)){
if(unit->getType()->isCommandable() && unit->getType()->hasCommandClass(ability)){
if(!idleOnly || !unit->anyCommand() || unit->getCurrCommand()->getCommandType()->getClass()==ccStop){
units.push_back(i);
}
@ -553,55 +553,57 @@ vector<int> Ai::findUnitsHarvestingResourceType(const ResourceType *rt) {
Map *map= aiInterface->getMap();
for(int i = 0; i < aiInterface->getMyUnitCount(); ++i) {
const Unit *unit= aiInterface->getMyUnit(i);
if(unit->getType()->hasCommandClass(ccHarvest)) {
if(unit->anyCommand() && unit->getCurrCommand()->getCommandType()->getClass() == ccHarvest) {
Command *command= unit->getCurrCommand();
const HarvestCommandType *hct= dynamic_cast<const HarvestCommandType*>(command->getCommandType());
if(hct != NULL) {
const Vec2i unitTargetPos = unit->getTargetPos();
SurfaceCell *sc= map->getSurfaceCell(Map::toSurfCoords(unitTargetPos));
Resource *r= sc->getResource();
if (r != NULL && r->getType() == rt) {
units.push_back(i);
}
}
}
}
else if(unit->getType()->hasCommandClass(ccProduce)) {
if(unit->anyCommand() && unit->getCurrCommand()->getCommandType()->getClass() == ccProduce) {
Command *command= unit->getCurrCommand();
const ProduceCommandType *pct= dynamic_cast<const ProduceCommandType*>(command->getCommandType());
if(pct != NULL) {
const UnitType *ut = pct->getProducedUnit();
if(ut != NULL) {
const Resource *r = ut->getCost(rt);
if(r != NULL) {
if (r != NULL && r->getAmount() < 0) {
units.push_back(i);
}
if(unit->getType()->isCommandable()) {
if(unit->getType()->hasCommandClass(ccHarvest)) {
if(unit->anyCommand() && unit->getCurrCommand()->getCommandType()->getClass() == ccHarvest) {
Command *command= unit->getCurrCommand();
const HarvestCommandType *hct= dynamic_cast<const HarvestCommandType*>(command->getCommandType());
if(hct != NULL) {
const Vec2i unitTargetPos = unit->getTargetPos();
SurfaceCell *sc= map->getSurfaceCell(Map::toSurfCoords(unitTargetPos));
Resource *r= sc->getResource();
if (r != NULL && r->getType() == rt) {
units.push_back(i);
}
}
}
}
}
}
}
else if(unit->getType()->hasCommandClass(ccBuild)) {
if(unit->anyCommand() && unit->getCurrCommand()->getCommandType()->getClass() == ccBuild) {
Command *command= unit->getCurrCommand();
const BuildCommandType *bct= dynamic_cast<const BuildCommandType*>(command->getCommandType());
if(bct != NULL) {
for(int j = 0; j < bct->getBuildingCount(); ++j) {
const UnitType *ut = bct->getBuilding(j);
else if(unit->getType()->hasCommandClass(ccProduce)) {
if(unit->anyCommand() && unit->getCurrCommand()->getCommandType()->getClass() == ccProduce) {
Command *command= unit->getCurrCommand();
const ProduceCommandType *pct= dynamic_cast<const ProduceCommandType*>(command->getCommandType());
if(pct != NULL) {
const UnitType *ut = pct->getProducedUnit();
if(ut != NULL) {
const Resource *r = ut->getCost(rt);
if(r != NULL) {
if (r != NULL && r->getAmount() < 0) {
units.push_back(i);
break;
}
}
}
}
}
}
}
}
else if(unit->getType()->hasCommandClass(ccBuild)) {
if(unit->anyCommand() && unit->getCurrCommand()->getCommandType()->getClass() == ccBuild) {
Command *command= unit->getCurrCommand();
const BuildCommandType *bct= dynamic_cast<const BuildCommandType*>(command->getCommandType());
if(bct != NULL) {
for(int j = 0; j < bct->getBuildingCount(); ++j) {
const UnitType *ut = bct->getBuilding(j);
if(ut != NULL) {
const Resource *r = ut->getCost(rt);
if(r != NULL) {
if (r != NULL && r->getAmount() < 0) {
units.push_back(i);
break;
}
}
}
}
}
}
}
}
}
@ -614,7 +616,7 @@ vector<int> Ai::findUnitsDoingCommand(CommandClass currentCommand) {
for(int i = 0; i < aiInterface->getMyUnitCount(); ++i) {
const Unit *unit= aiInterface->getMyUnit(i);
if(unit->getType()->hasCommandClass(currentCommand)) {
if(unit->getType()->isCommandable() && unit->getType()->hasCommandClass(currentCommand)) {
if(unit->anyCommand() && unit->getCurrCommand()->getCommandType()->getClass() == currentCommand) {
units.push_back(i);
}
@ -630,7 +632,7 @@ bool Ai::findAbleUnit(int *unitIndex, CommandClass ability, CommandClass current
*unitIndex= -1;
for(int i=0; i<aiInterface->getMyUnitCount(); ++i){
const Unit *unit= aiInterface->getMyUnit(i);
if(unit->getType()->hasCommandClass(ability)){
if(unit->getType()->isCommandable() && unit->getType()->hasCommandClass(ability)){
if(unit->anyCommand() && unit->getCurrCommand()->getCommandType()->getClass()==currentCommand){
units.push_back(i);
}

View File

@ -103,21 +103,29 @@ void ChatManager::keyDown(SDL_KeyboardEvent key) {
Config &configKeys = Config::getInstance(std::pair<ConfigType,ConfigType>(cfgMainKeys,cfgUserKeys));
//toggle team mode
if(editEnabled == false && disableTeamMode == false &&
if(editEnabled == false &&
isKeyPressed(configKeys.getSDLKey("ChatTeamMode"),key) == true) {
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] key = [%c] [%d]\n",__FILE__,__FUNCTION__,__LINE__,key.keysym.sym,key.keysym.sym);
if(disableTeamMode == true) {
if (!inMenu) {
console->addLine(lang.getString("ChatModeDisabledToAvoidCheating") );
}
}
else {
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] key = [%c] [%d]\n",__FILE__,__FUNCTION__,__LINE__,key.keysym.sym,key.keysym.sym);
if (!inMenu) {
if (teamMode == true) {
teamMode = false;
console->addLine(lang.getString("ChatMode") + ": " + lang.getString("All"));
} else {
teamMode = true;
console->addLine(lang.getString("ChatMode") + ": " + lang.getString("Team"));
if (!inMenu) {
if (teamMode == true) {
teamMode = false;
console->addLine(lang.getString("ChatMode") + ": " + lang.getString("All"));
} else {
teamMode = true;
console->addLine(lang.getString("ChatMode") + ": " + lang.getString("Team"));
}
}
}
}
if(isKeyPressed(SDLK_RETURN,key, false) == true) {
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] key = [%c] [%d]\n",__FILE__,__FUNCTION__,__LINE__,key.keysym.sym,key.keysym.sym);

View File

@ -5391,18 +5391,20 @@ string Game::getDebugStats(std::map<int,string> &factionDebugInfo) {
for(int i = 0; i < world.getFactionCount(); ++i) {
string factionInfo = this->gameSettings.getNetworkPlayerName(i);
//factionInfo += " [" + this->gameSettings.getNetworkPlayerUUID(i) + "]";
float multi=world.getStats()->getResourceMultiplier(i);
string multiplier="["+floatToStr(multi,1)+"]";
switch(this->gameSettings.getFactionControl(i)) {
case ctCpuEasy:
factionInfo += " CPU Easy";
factionInfo += " CPU Easy"+multiplier;
break;
case ctCpu:
factionInfo += " CPU Normal";
factionInfo += " CPU Normal"+multiplier;
break;
case ctCpuUltra:
factionInfo += " CPU Ultra";
factionInfo += " CPU Ultra"+multiplier;
break;
case ctCpuMega:
factionInfo += " CPU Mega";
factionInfo += " CPU Mega"+multiplier;
break;
}

View File

@ -1531,6 +1531,12 @@ int ScriptManager::getUnitFaction(int unitId) {
const string ScriptManager::getUnitName(int unitId) {
if(SystemFlags::getSystemSettingType(SystemFlags::debugLUA).enabled) SystemFlags::OutputDebug(SystemFlags::debugLUA,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
return world->findUnitById(unitId)->getType()->getName(false);
}
const string ScriptManager::getUnitDisplayName(int unitId) {
if(SystemFlags::getSystemSettingType(SystemFlags::debugLUA).enabled) SystemFlags::OutputDebug(SystemFlags::debugLUA,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
return world->getUnitName(unitId);
}
@ -3414,6 +3420,7 @@ int ScriptManager::getUnitFaction(LuaHandle* luaHandle){
return luaArguments.getReturnCount();
}
int ScriptManager::getUnitName(LuaHandle* luaHandle){
LuaArguments luaArguments(luaHandle);
try {
@ -3435,6 +3442,28 @@ int ScriptManager::getUnitName(LuaHandle* luaHandle){
return luaArguments.getReturnCount();
}
int ScriptManager::getUnitDisplayName(LuaHandle* luaHandle){
LuaArguments luaArguments(luaHandle);
try {
const string unitname = thisScriptManager->getUnitDisplayName(luaArguments.getInt(-1));
luaArguments.returnString(unitname);
}
catch(const megaglest_runtime_error &ex) {
char szErrBuf[8096]="";
snprintf(szErrBuf,8096,"In [%s::%s %d]",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
string sErrBuf = string(szErrBuf) + string("\nThe game may no longer be stable!\nerror [") + string(ex.what()) + string("]\n");
SystemFlags::OutputDebug(SystemFlags::debugError,sErrBuf.c_str());
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,sErrBuf.c_str());
thisScriptManager->addMessageToQueue(ScriptManagerMessage(sErrBuf.c_str(), "error",-1,-1,true));
thisScriptManager->onMessageBoxOk(false);
}
return luaArguments.getReturnCount();
}
int ScriptManager::getResourceAmount(LuaHandle* luaHandle){
LuaArguments luaArguments(luaHandle);
try {

View File

@ -356,6 +356,7 @@ private:
Vec2i getUnitPosition(int unitId);
int getUnitFaction(int unitId);
const string getUnitName(int unitId);
const string getUnitDisplayName(int unitId);
int getResourceAmount(const string &resourceName, int factionIndex);
const string &getLastCreatedUnitName();
int getLastCreatedUnitId();
@ -521,6 +522,7 @@ private:
static int getUnitPosition(LuaHandle* luaHandle);
static int getUnitFaction(LuaHandle* luaHandle);
static int getUnitName(LuaHandle* luaHandle);
static int getUnitDisplayName(LuaHandle* luaHandle);
static int getResourceAmount(LuaHandle* luaHandle);
static int getLastCreatedUnitName(LuaHandle* luaHandle);
static int getLastCreatedUnitId(LuaHandle* luaHandle);

View File

@ -3,9 +3,9 @@
//
// Copyright (C) 2010-2010 Titus Tscharntke
//
// 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
// 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
// ==============================================================
@ -57,6 +57,8 @@ ParticleSystemType::ParticleSystemType() {
size=0;
sizeNoEnergy=0;
speed=0;
speedUpRelative=0;
speedUpConstant=0;
gravity=0;
emissionRate=0;
energyMax=0;
@ -107,6 +109,8 @@ void ParticleSystemType::copyAll(const ParticleSystemType &src) {
this->size = src.size;
this->sizeNoEnergy = src.sizeNoEnergy;
this->speed = src.speed;
this->speedUpRelative = src.speedUpRelative;
this->speedUpConstant = src.speedUpConstant;
this->gravity = src.gravity;
this->emissionRate = src.emissionRate;
this->energyMax = src.energyMax;
@ -160,7 +164,7 @@ void ParticleSystemType::load(const XmlNode *particleSystemNode, const string &d
else {
texture= NULL;
}
//model
if(particleSystemNode->hasChild("model")){
const XmlNode *modelNode= particleSystemNode->getChild("model");
@ -172,7 +176,7 @@ void ParticleSystemType::load(const XmlNode *particleSystemNode, const string &d
string path= modelNode->getAttribute("path")->getRestrictedValue(currentPath);
model= renderer->newModel(rsGame,path, false, &loadedFileList, &parentLoader);
loadedFileList[path].push_back(make_pair(parentLoader,modelNode->getAttribute("path")->getRestrictedValue()));
if(modelNode->hasChild("cycles")) {
modelCycle = modelNode->getChild("cycles")->getAttribute("value")->getFloatValue();
if(modelCycle < 0.0)
@ -220,6 +224,17 @@ void ParticleSystemType::load(const XmlNode *particleSystemNode, const string &d
const XmlNode *speedNode= particleSystemNode->getChild("speed");
speed= speedNode->getAttribute("value")->getFloatValue()/GameConstants::updateFps;
//speedUp
if(particleSystemNode->hasChild("speedUp")){
const XmlNode *speedUpNode= particleSystemNode->getChild("speedUp");
if(speedUpNode->hasAttribute("relative")){
speedUpRelative= speedUpNode->getAttribute("relative")->getFloatValue();
}
if(speedUpNode->hasAttribute("constant")){
speedUpConstant= speedUpNode->getAttribute("constant")->getFloatValue();
}
}
//gravity
const XmlNode *gravityNode= particleSystemNode->getChild("gravity");
gravity= gravityNode->getAttribute("value")->getFloatValue()/GameConstants::updateFps;
@ -235,7 +250,7 @@ void ParticleSystemType::load(const XmlNode *particleSystemNode, const string &d
//speed
const XmlNode *energyVarNode= particleSystemNode->getChild("energy-var");
energyVar= energyVarNode->getAttribute("value")->getIntValue();
//teamcolorNoEnergy
if(particleSystemNode->hasChild("teamcolorNoEnergy")){
const XmlNode *teamcolorNoEnergyNode= particleSystemNode->getChild("teamcolorNoEnergy");
@ -300,6 +315,8 @@ void ParticleSystemType::setValues(AttackParticleSystem *ats){
ats->setColor(color);
ats->setColorNoEnergy(colorNoEnergy);
ats->setSpeed(speed);
ats->setSpeedUpRelative(speedUpRelative);
ats->setSpeedUpConstant(speedUpConstant);
ats->setGravity(gravity);
ats->setParticleSize(size);
ats->setSizeNoEnergy(sizeNoEnergy);
@ -328,6 +345,8 @@ void ParticleSystemType::loadGame(const XmlNode *rootNode) {
size = particleSystemTypeNode->getAttribute("size")->getFloatValue();
sizeNoEnergy = particleSystemTypeNode->getAttribute("sizeNoEnergy")->getFloatValue();
speed = particleSystemTypeNode->getAttribute("speed")->getFloatValue();
speedUpRelative = particleSystemTypeNode->getAttribute("speedUpRelative")->getFloatValue();
speedUpConstant = particleSystemTypeNode->getAttribute("speedUpConstant")->getFloatValue();
gravity = particleSystemTypeNode->getAttribute("gravity")->getFloatValue();
emissionRate = particleSystemTypeNode->getAttribute("emissionRate")->getFloatValue();
energyMax = particleSystemTypeNode->getAttribute("energyMax")->getIntValue();
@ -379,6 +398,10 @@ void ParticleSystemType::saveGame(XmlNode *rootNode) {
particleSystemTypeNode->addAttribute("sizeNoEnergy",floatToStr(sizeNoEnergy,6), mapTagReplacements);
// float speed;
particleSystemTypeNode->addAttribute("speed",floatToStr(speed,6), mapTagReplacements);
// float speedUpRelative;
particleSystemTypeNode->addAttribute("speedUpRelative",floatToStr(speedUpRelative,6), mapTagReplacements);
// float speedUpConstant;
particleSystemTypeNode->addAttribute("speedUpConstant",floatToStr(speedUpConstant,6), mapTagReplacements);
// float gravity;
particleSystemTypeNode->addAttribute("gravity",floatToStr(gravity,6), mapTagReplacements);
// float emissionRate;
@ -441,7 +464,7 @@ void ParticleSystemTypeProjectile::load(const XmlNode* particleFileNode, const s
particleFileNode->setSuper(particleSystemNode);
particleSystemNode= particleFileNode;
}
ParticleSystemType::load(particleSystemNode, dir, renderer, loadedFileList,parentLoader, techtreePath);
//trajectory values
@ -535,7 +558,7 @@ void ParticleSystemTypeSplash::load(const XmlNode* particleFileNode, const strin
loadedFileList[path].push_back(make_pair(parentLoader,parentLoader));
const XmlNode *particleSystemNode= xmlTree.getRootNode();
if(particleFileNode){
// immediate children in the particleFileNode will override the particleSystemNode
particleFileNode->setSuper(particleSystemNode);
@ -547,7 +570,7 @@ void ParticleSystemTypeSplash::load(const XmlNode* particleFileNode, const strin
//emission rate fade
const XmlNode *emissionRateFadeNode= particleSystemNode->getChild("emission-rate-fade");
emissionRateFade= emissionRateFadeNode->getAttribute("value")->getFloatValue();
//spread values
const XmlNode *verticalSpreadNode= particleSystemNode->getChild("vertical-spread");
verticalSpreadA= verticalSpreadNode->getAttribute("a")->getFloatValue(0.0f, 1.0f);

View File

@ -65,6 +65,8 @@ protected:
float size;
float sizeNoEnergy;
float speed;
float speedUpRelative;
float speedUpConstant;
float gravity;
float emissionRate;
int energyMax;

View File

@ -233,6 +233,8 @@ const void UnitParticleSystemType::setValues(UnitParticleSystem *ups){
ups->setColor(color);
ups->setColorNoEnergy(colorNoEnergy);
ups->setSpeed(speed);
ups->setSpeedUpRelative(speedUpRelative);
ups->setSpeedUpConstant(speedUpConstant);
ups->setGravity(gravity);
ups->setParticleSize(size);
ups->setSizeNoEnergy(sizeNoEnergy);

View File

@ -71,6 +71,11 @@ bool Selection::select(Unit *unit) {
return false;
}
//check if commandable
if(unit->getType()->isCommandable() == false && isEmpty() == false) {
return false;
}
//check if multisel
if(unit->getType()->getMultiSelect() == false && isEmpty() == false) {
return false;
@ -181,7 +186,8 @@ bool Selection::isCommandable() const {
return
isEmpty() == false &&
isEnemy() == false &&
(selectedUnits.size() == 1 && selectedUnits.front()->isAlive() == false) == false;
(selectedUnits.size() == 1 && selectedUnits.front()->isAlive() == false) == false &&
selectedUnits.front()->getType()->isCommandable();
}
bool Selection::isCancelable() const {

View File

@ -101,6 +101,14 @@ using namespace Shared::Graphics::Gl;
using namespace Shared::Xml;
using namespace Shared;
/**
* @namespace Glest
* Namespace used for all %Glest related code.
*/
/**
* @namespace Game
* Namespace used for game related code.
*/
namespace Glest { namespace Game {
static string tempDataLocation = getUserHome();

View File

@ -1209,7 +1209,7 @@ void Faction::applyCostsOnInterval(const ResourceType *rtApply) {
world->getStats()->die(unit->getFactionIndex(),unit->getType()->getCountUnitDeathInStats());
scriptManager->onUnitDied(unit);
}
StaticSound *sound= unit->getType()->getFirstStOfClass(scDie)->getSound();
StaticSound *sound= static_cast<const DieSkillType *>(unit->getType()->getFirstStOfClass(scDie))->getSound();
if(sound != NULL &&
(thisFaction == true || world->showWorldForPlayer(world->getThisTeamIndex()) == true)) {
SoundRenderer::getInstance().playFx(sound);

View File

@ -666,27 +666,7 @@ Unit::~Unit() {
}
safeMutex.ReleaseLock();
// If the unit is not visible we better make sure we cleanup associated particles
if(this->getVisible() == false) {
Renderer::getInstance().cleanupUnitParticleSystems(unitParticleSystems,rsGame);
Renderer::getInstance().cleanupParticleSystems(fireParticleSystems,rsGame);
// Must set this to null of it will be used below in stopDamageParticles()
if(Renderer::getInstance().validateParticleSystemStillExists(this->fire,rsGame) == false) {
this->fire = NULL;
}
}
// fade(and by this remove) all unit particle systems
queuedUnitParticleSystemTypes.clear();
while(unitParticleSystems.empty() == false) {
if(Renderer::getInstance().validateParticleSystemStillExists(unitParticleSystems.back(),rsGame) == true) {
unitParticleSystems.back()->fade();
}
unitParticleSystems.pop_back();
}
stopDamageParticles(true);
cleanupAllParticlesystems();
while(currentAttackBoostEffects.empty() == false) {
//UnitAttackBoostEffect &effect = currentAttackBoostEffects.back();
@ -726,6 +706,29 @@ Unit::~Unit() {
#endif
}
void Unit::cleanupAllParticlesystems() {
Renderer::getInstance().cleanupUnitParticleSystems(unitParticleSystems,rsGame);
Renderer::getInstance().cleanupParticleSystems(fireParticleSystems,rsGame);
// Must set this to null of it will be used below in stopDamageParticles()
if(Renderer::getInstance().validateParticleSystemStillExists(this->fire,rsGame) == false) {
this->fire = NULL;
}
// fade(and by this remove) all unit particle systems
queuedUnitParticleSystemTypes.clear();
while(unitParticleSystems.empty() == false) {
if(Renderer::getInstance().validateParticleSystemStillExists(unitParticleSystems.back(),rsGame) == true) {
unitParticleSystems.back()->fade();
}
unitParticleSystems.pop_back();
}
stopDamageParticles(true);
}
ParticleSystem * Unit::getFire() const {
if(this->fire != NULL &&
Renderer::getInstance().validateParticleSystemStillExists(this->fire,rsGame) == false) {
@ -1951,13 +1954,32 @@ void Unit::born(const CommandType *ct) {
checkItemInVault(&this->hp,this->hp);
int original_hp = this->hp;
this->hp= type->getMaxHp();
//set hp from start hp
checkItemInVault(&this->ep,this->ep);
if(type->getStartHpType() == UnitType::stValue) {
this->hp= type->getStartHpValue();
}
else {
this->hp= type->getTotalMaxHp(&totalUpgrade) * 100 / type->getStartHpPercentage();
}
if(original_hp != this->hp) {
//printf("File: %s line: %d\n",extractFileFromDirectoryPath(__FILE__).c_str(),__LINE__);
game->getScriptManager()->onUnitTriggerEvent(this,utet_HPChanged);
//printf("File: %s line: %d\n",extractFileFromDirectoryPath(__FILE__).c_str(),__LINE__);
}
addItemToVault(&this->hp,this->hp);
//set ep from start ep
checkItemInVault(&this->ep,this->ep);
if(type->getStartEpType() == UnitType::stValue) {
this->ep= type->getStartEpValue();
}
else {
this->ep= type->getTotalMaxEp(&totalUpgrade) * 100 / type->getStartEpPercentage();
}
}
void Unit::kill() {
@ -2611,7 +2633,15 @@ bool Unit::update() {
int64 heightFactor = getHeightFactor(ANIMATION_SPEED_MULTIPLIER);
int64 speedDenominator = speedDivider *
game->getWorld()->getUpdateFps(this->getFactionIndex());
int64 progressIncrease = (currSkill->getAnimSpeed() * heightFactor) / speedDenominator;
// Override the animation speed for attacks that have upgraded the attack speed
int animSpeed = currSkill->getAnimSpeed();
if(currSkill->getClass() == scAttack) {
int animSpeedBoost = ((AttackSkillType *) currSkill)->getAnimSpeedBoost(&totalUpgrade);
animSpeed += animSpeedBoost;
}
int64 progressIncrease = (animSpeed * heightFactor) / speedDenominator;
// Ensure we increment at least a value of 1 of the action will be stuck infinitely
if(currSkill->getAnimSpeed() > 0 && heightFactor > 0 && progressIncrease == 0) {
progressIncrease = 1;
@ -2933,7 +2963,7 @@ bool Unit::applyAttackBoost(const AttackBoost *boost, const Unit *source) {
Unit::game->getWorld()->getStats()->die(getFactionIndex(),getType()->getCountUnitDeathInStats());
game->getScriptManager()->onUnitDied(this);
StaticSound *sound= this->getType()->getFirstStOfClass(scDie)->getSound();
StaticSound *sound= static_cast<const DieSkillType *>(this->getType()->getFirstStOfClass(scDie))->getSound();
if(sound != NULL &&
(this->getFactionIndex() == Unit::game->getWorld()->getThisFactionIndex() ||
(game->getWorld()->showWorldForPlayer(game->getWorld()->getThisTeamIndex()) == true))) {
@ -3031,7 +3061,7 @@ void Unit::deapplyAttackBoost(const AttackBoost *boost, const Unit *source) {
Unit::game->getWorld()->getStats()->die(getFactionIndex(),getType()->getCountUnitDeathInStats());
game->getScriptManager()->onUnitDied(this);
StaticSound *sound= this->getType()->getFirstStOfClass(scDie)->getSound();
StaticSound *sound= static_cast<const DieSkillType *>(this->getType()->getFirstStOfClass(scDie))->getSound();
if(sound != NULL &&
(this->getFactionIndex() == Unit::game->getWorld()->getThisFactionIndex() ||
(game->getWorld()->showWorldForPlayer(game->getWorld()->getThisTeamIndex()) == true))) {
@ -3103,7 +3133,7 @@ void Unit::tick() {
Unit::game->getWorld()->getStats()->die(getFactionIndex(),getType()->getCountUnitDeathInStats());
game->getScriptManager()->onUnitDied(this);
}
StaticSound *sound= this->getType()->getFirstStOfClass(scDie)->getSound();
StaticSound *sound= static_cast<const DieSkillType *>(this->getType()->getFirstStOfClass(scDie))->getSound();
if(sound != NULL &&
(this->getFactionIndex() == Unit::game->getWorld()->getThisFactionIndex() ||
(game->getWorld()->showWorldForPlayer(game->getWorld()->getThisTeamIndex()) == true))) {
@ -3142,7 +3172,7 @@ void Unit::tick() {
Unit::game->getWorld()->getStats()->die(getFactionIndex(),getType()->getCountUnitDeathInStats());
game->getScriptManager()->onUnitDied(this);
}
StaticSound *sound= this->getType()->getFirstStOfClass(scDie)->getSound();
StaticSound *sound= static_cast<const DieSkillType *>(this->getType()->getFirstStOfClass(scDie))->getSound();
if(sound != NULL &&
(this->getFactionIndex() == Unit::game->getWorld()->getThisFactionIndex() ||
(game->getWorld()->showWorldForPlayer(game->getWorld()->getThisTeamIndex()) == true))) {
@ -3553,6 +3583,8 @@ bool Unit::morph(const MorphCommandType *mct) {
}
}
//stopDamageParticles(true);
cleanupAllParticlesystems();
checkItemInVault(&this->hp,this->hp);
int original_hp = this->hp;

View File

@ -806,6 +806,7 @@ public:
private:
void cleanupAllParticlesystems();
bool isNetworkCRCEnabled();
string getNetworkCRCDecHpList() const;
string getParticleInfo() const;

View File

@ -9,6 +9,13 @@
// License, or (at your option) any later version
// ==============================================================
/**
* @file
* Contains the Upgrade and UpgradeManager classes. This is what the factions need to manage
* upgrades (including starting, canceling, and finishing upgrades, figuring out which
* upgrades we have done, etc).
*/
#ifndef _GLEST_GAME_UPGRADE_H_
#define _GLEST_GAME_UPGRADE_H_
@ -33,25 +40,32 @@ class Unit;
class UpgradeType;
class Faction;
/**
* Stores the state of the upgrade (whether or not the upgrading process is complete).
*/
// TODO: Don't make this global; move it inside Upgrade
enum UpgradeState {
usUpgrading,
usUpgraded,
usUpgrading, /**< The upgrade is currently in progress. */
usUpgraded, /**< The upgrade is completed. */
upgradeStateCount
upgradeStateCount // TODO: This should be unnecessary -- there's no need to iterate over this enum
};
class UpgradeManager;
class TotalUpgrade;
// =====================================================
// class Upgrade
//
/// A bonus to an UnitType
// =====================================================
/**
* An instance of an upgrade. Factions will typically have one upgrade of each type. This object
* groups the type, faction, and upgrade state (ie, has the upgrade been obtained yet?).
*/
class Upgrade {
private:
UpgradeState state;
// TODO: I believe this is unnecessary. As far as I can tell, it's only used for checking
// that the unit we're applying UpgradeManager::computeTotalUpgrade to is in this faction. However,
// I don't see an circumstances when it wouldn't be (since the UpgradeManager already an aggregate
// of a faction and Unit directly gets the UpgradeManager from the faction (so it must have the
// same faction as the upgrades in the UpgradeManager).
int factionIndex;
const UpgradeType *type;
@ -59,50 +73,136 @@ private:
Upgrade();
public:
/**
* Creates an upgrade. The upgrade state will be set to UpgradeState::usUpgrading.
* @param upgradeType The type of the upgrade that this corresponds to. Upgrade types are
* essentially "classes" for upgrades.
* @param factionIndex The index of the faction that the upgrade belongs to.
*/
Upgrade(const UpgradeType *upgradeType, int factionIndex);
private:
//get
UpgradeState getState() const;
int getFactionIndex() const;
const UpgradeType * getType() const;
//set
void setState(UpgradeState state);
/**
* Retrieves a string representation of the upgrade (detailing its state, type, and faction).
*/
std::string toString() const;
/**
* Saves the object state into the given node.
* @param rootNode The UpgradeManager node to save object info to.
*/
void saveGame(XmlNode *rootNode);
/**
* Loads the object state from the given node.
* @param rootNode The UpgradeManager node to retrieve object info from.
* @param faction The faction that the upgrade belongs to. Used to convert the upgrade type from
* the XML string.
*/
static Upgrade * loadGame(const XmlNode *rootNode,Faction *faction);
};
// ===============================
// class UpgradeManager
// ===============================
/**
* Manages upgrades by starting, stopping, and finishing upgrades. Each faction has their own
* upgrade manager.
*/
class UpgradeManager{
private:
private:
typedef vector<Upgrade*> Upgrades;
typedef map<const UpgradeType *,int> UgradesLookup;
/**
* List of upgrades that the upgrade manager is working with (either in progress or finished).
*/
Upgrades upgrades;
/**
* Maps UpgradeType to the index of the upgrade in UpgradeManager::upgrades.
*/
UgradesLookup upgradesLookup;
public:
~UpgradeManager();
int getUpgradeCount() const {return (int)upgrades.size();}
/**
* Starts an upgrade.
* @param upgradeType The type of the upgrade to start.
* @param factionIndex Passed to the constructor of the Upgrade.
*/
void startUpgrade(const UpgradeType *upgradeType, int factionIndex);
/**
* Cancels an upgrade before it is finished. The upgrade is removed from the UpgradeManager.
* @param upgradeType The type of the upgrade to remove.
* @throws megaglest_runtime_error If there is no upgrade of the desired type in the UpgradeManager.
*/
void cancelUpgrade(const UpgradeType *upgradeType);
/**
* Sets an Upgrade in the UpgradeManager as finished (ie, the state is UpgradeState::usUpgraded).
* @param upgradeType The type of the upgrade to complete.
* @throws megaglest_runtime_error If there is no upgrade of the desired type in the UpgradeManager.
*/
void finishUpgrade(const UpgradeType *upgradeType);
/**
* Returns true if an Upgrade of the desired type has state UpgradeState::usUpgraded (ie, is
* finished upgrading).
* @param upgradeType The type of the upgrade in question.
*/
bool isUpgraded(const UpgradeType *upgradeType) const;
bool isUpgrading(const UpgradeType *upgradeType) const;
bool isUpgradingOrUpgraded(const UpgradeType *upgradeType) const;
void computeTotalUpgrade(const Unit *unit, TotalUpgrade *totalUpgrade) const;
/**
* Returns true if an Upgrade of the desired type has state UpgradeState::usUpgrading (ie, is
* currently in progress).
* @param upgradeType The type of the upgrade in question.
*/
bool isUpgrading(const UpgradeType *upgradeType) const;
/**
* Returns true if an Upgrade of the desired type exists in the UpgradeManager.
* @param upgradeType The type of the upgrade in question.
*/
bool isUpgradingOrUpgraded(const UpgradeType *upgradeType) const;
/**
* [Sums up](@ref TotalUpgrade::sum) the effect of all upgrades for this faction as they apply
* to a particular unit.
* @param unit The unit that the TotalUpgrade applies to. This is necessary because some
* upgrades provide percentage boosts.
* @param totalUpgrade The TotalUpgrade object to modify. Note that it is cleared before values
* are calculated.
*/
void computeTotalUpgrade(const Unit *unit, TotalUpgrade *totalUpgrade) const;
/**
* Retrieves a string representation of the UpgradeManager. Contains the contents of
* Upgrade::toString for all upgrades in the UpgradeManager.
*/
std::string toString() const;
/**
* Adds a node for the UpgradeManager that contains all the upgrade nodes, saving the object's
* state.
* @param rootNode The faction node to add the UpgradeManager node to.
* @see Upgrade::saveGame
*/
void saveGame(XmlNode *rootNode);
/**
* Loads all the upgrades from the UpgradeManager node, effectively reloading the object's
* state.
* @param rootNode The faction node to get the UpgradeManager node from.
* @param faction Only passed to Upgrade::loadGame (which does the actual loading of each
* Upgrade object.
*/
void loadGame(const XmlNode *rootNode,Faction *faction);
};

View File

@ -288,7 +288,13 @@ string AttackCommandType::getDesc(const TotalUpgrade *totalUpgrade, bool transla
}
str+="\n";
//attack speed
str+= lang.getString("AttackSpeed",(translatedValue == true ? "" : "english"))+": "+ intToStr(attackSkillType->getSpeed()) +"\n";
if(totalUpgrade->getAttackSpeed(attackSkillType) != 0) {
str+= "+"+intToStr(totalUpgrade->getAttackSpeed(attackSkillType));
}
str+="\n";
str+=attackSkillType->getBoostDesc(translatedValue);
return str;
}

View File

@ -0,0 +1,126 @@
// ==============================================================
// 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 <cassert>
#include "logger.h"
#include "lang.h"
#include "renderer.h"
#include "leak_dumper.h"
using namespace Shared::Util;
namespace Glest{ namespace Game{
ProjectileType::ProjectileType() {
projectileParticleSystemType=NULL;
attackStartTime=0.0f;
spawnUnit="";
spawnUnitcount=0;
spawnUnitAtTarget=false;
shake=false;
shakeIntensity=0;
shakeDuration=0;
shakeVisible=true;
shakeInCameraView=true;
shakeCameraDistanceAffected=false;
damagePercentage=100;
}
ProjectileType::~ProjectileType() {
deleteValues(hitSounds.getSounds().begin(), hitSounds.getSounds().end());
if(projectileParticleSystemType!=NULL){
delete projectileParticleSystemType;
projectileParticleSystemType = NULL;
}
}
void ProjectileType::load(const XmlNode *projectileNode, const string &dir, const string &techtreepath, std::map<string,vector<pair<string, string> > > &loadedFileList,
string parentLoader){
string currentPath = dir;
endPathWithSlash(currentPath);
if(projectileNode->hasAttribute("attack-start-time")){
attackStartTime =projectileNode->getAttribute("attack-start-time")->getFloatValue();
}
else
{
attackStartTime=0.0f;
}
// damage percentage MUST be set!
damagePercentage =projectileNode->getAttribute("damage-percentage")->getIntValue();
// projectiles MUST have a particle system.
const XmlNode *particleNode= projectileNode->getChild("particle");
string path= particleNode->getAttribute("path")->getRestrictedValue();
ParticleSystemTypeProjectile* projectileParticleSystemType= new ParticleSystemTypeProjectile();
projectileParticleSystemType->load(particleNode, dir, currentPath + path,
&Renderer::getInstance(), loadedFileList, parentLoader,
techtreepath);
loadedFileList[currentPath + path].push_back(make_pair(parentLoader,particleNode->getAttribute("path")->getRestrictedValue()));
setProjectileParticleSystemType(projectileParticleSystemType);
//spawnattack
if (projectileNode->hasChild("unit")) {
spawnUnit = projectileNode->getChild("unit")->getAttribute("value")->getValue();
spawnUnitcount = projectileNode->getChild("unit")->getAttribute("amount")->getIntValue();
if(projectileNode->getChild("unit")->hasAttribute("spawnAtTarget")) {
spawnUnitAtTarget = projectileNode->getChild("unit")->getAttribute("spawnAtTarget")->getBoolValue();
} else {
spawnUnitAtTarget = false;
}
} else {
spawnUnit = "";
spawnUnitcount = 0;
spawnUnitAtTarget = false;
}
if(projectileNode->hasChild("hitshake")){
const XmlNode *hitShakeNode= projectileNode->getChild("hitshake");
shake=hitShakeNode->getAttribute("enabled")->getBoolValue();
if(shake){
shakeIntensity=hitShakeNode->getAttribute("intensity")->getIntValue();
shakeDuration=hitShakeNode->getAttribute("duration")->getIntValue();
shakeVisible=hitShakeNode->getAttribute("visible")->getBoolValue();
shakeInCameraView=hitShakeNode->getAttribute("in-camera-view")->getBoolValue();
shakeCameraDistanceAffected=hitShakeNode->getAttribute("camera-distance-affected")->getBoolValue();
}
}
if(projectileNode->hasChild("hitsound")){
const XmlNode *soundNode= projectileNode->getChild("hitsound");
if(soundNode->getAttribute("enabled")->getBoolValue()){
hitSounds.resize((int)soundNode->getChildCount());
for(int i=0; i < (int)soundNode->getChildCount(); ++i){
const XmlNode *soundFileNode= soundNode->getChild("sound-file", i);
string path= soundFileNode->getAttribute("path")->getRestrictedValue(currentPath, true);
//printf("\n\n\n\n!@#$ ---> parentLoader [%s] path [%s] nodeValue [%s] i = %d",parentLoader.c_str(),path.c_str(),soundFileNode->getAttribute("path")->getRestrictedValue().c_str(),i);
StaticSound *sound= new StaticSound();
sound->load(path);
loadedFileList[path].push_back(make_pair(parentLoader,soundFileNode->getAttribute("path")->getRestrictedValue()));
hitSounds[i]= sound;
}
}
}
}
}}//end namespace

View File

@ -0,0 +1,90 @@
// ==============================================================
// 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
// ==============================================================
#ifndef _GLEST_GAME_PROJEKTILETYPE_H_
#define _GLEST_GAME_PROJEKTILETYPE_H_
#ifdef WIN32
#include <winsock2.h>
#include <winsock.h>
#endif
#include "sound.h"
#include "vec.h"
//#include "xml_parser.h"
#include "util.h"
//#include "element_type.h"
#include "factory.h"
#include "sound_container.h"
#include "particle_type.h"
#include "leak_dumper.h"
using std::vector;
using std::string;
namespace Glest{ namespace Game{
// =====================================================
// class ProjectileType
// =====================================================
class ProjectileType {
protected:
ParticleSystemTypeProjectile* projectileParticleSystemType;
SoundContainer hitSounds;
float attackStartTime;
string spawnUnit;
int spawnUnitcount;
bool spawnUnitAtTarget;
bool shake;
int shakeIntensity;
int shakeDuration;
bool shakeVisible;
bool shakeInCameraView;
bool shakeCameraDistanceAffected;
int damagePercentage;
public:
ProjectileType();
virtual ~ProjectileType();
void load(const XmlNode *projectileNode, const string &dir, const string &techtreepath, std::map<string,vector<pair<string, string> > > &loadedFileList,
string parentLoader);
//get/set
inline StaticSound *getHitSound() const {return hitSounds.getRandSound();}
ParticleSystemTypeProjectile* getProjectileParticleSystemType() const { return projectileParticleSystemType;}
float getAttackStartTime() const {return attackStartTime;}
void setAttackStartTime(float value) {attackStartTime=value;}
string getSpawnUnit() const{return spawnUnit;}
int getSpawnUnitcount() const{return spawnUnitcount;}
bool getSpawnUnitAtTarget() const{return spawnUnitAtTarget;}
bool isShake() const{return shake;}
bool isShakeCameraDistanceAffected() const{return shakeCameraDistanceAffected;}
int getShakeDuration() const{return shakeDuration;}
bool isShakeInCameraView() const{return shakeInCameraView;}
int getShakeIntensity() const{return shakeIntensity;}
bool isShakeVisible() const{return shakeVisible;}
int getDamagePercentage() const {return damagePercentage;}
void setDamagePercentage(int value) {damagePercentage=value;}
void setProjectileParticleSystemType(ParticleSystemTypeProjectile *pointer) {projectileParticleSystemType=pointer;}
ParticleSystemTypeProjectile* getProjectileParticleSystemType() {return projectileParticleSystemType;}
};
}}//end namespace
#endif

View File

@ -19,6 +19,7 @@
#include "renderer.h"
#include "particle_type.h"
#include "unit_particle_type.h"
#include "projectile_type.h"
#include "tech_tree.h"
#include "faction_type.h"
#include "leak_dumper.h"
@ -273,12 +274,27 @@ void AttackBoost::saveGame(XmlNode *rootNode) const {
attackBoostNode->addAttribute("name",name, mapTagReplacements);
}
// =====================================================
// class SkillSound
// =====================================================
SkillSound::SkillSound(){
startTime=0.0f;
}
SkillSound::~SkillSound()
{
deleteValues(soundContainer.getSounds().begin(), soundContainer.getSounds().end());
startTime=0.0f;
//soundContainer
}
// =====================================================
// class SkillType
// =====================================================
SkillType::~SkillType() {
deleteValues(sounds.getSounds().begin(), sounds.getSounds().end());
while(!skillSoundList.empty()) {
delete skillSoundList.back();
skillSoundList.pop_back();
}
//remove unitParticleSystemTypes
while(!unitParticleSystemTypes.empty()) {
delete unitParticleSystemTypes.back();
@ -488,11 +504,18 @@ void SkillType::load(const XmlNode *sn, const XmlNode *attackBoostsNode,
unitParticleSystemType->load(particleFileNode, dir, currentPath + path, &Renderer::getInstance(),
loadedFileList,parentLoader,tt->getPath());
if(particleNode->getAttribute("start-time",false) != NULL) {
if (particleNode->getChild(i)->hasAttribute("start-time")) {
//printf("*NOTE particle system type has start-time [%f]\n",particleNode->getAttribute("start-time")->getFloatValue());
unitParticleSystemType->setStartTime(particleNode->getChild(i)->getAttribute("start-time")->getFloatValue());
} else if (particleNode->hasAttribute("start-time")) {
//printf("*NOTE particle system type has start-time [%f]\n",particleNode->getAttribute("start-time")->getFloatValue());
unitParticleSystemType->setStartTime(particleNode->getAttribute("start-time")->getFloatValue());
}
if(particleNode->getAttribute("end-time",false) != NULL) {
if (particleNode->getChild(i)->hasAttribute("end-time")) {
//printf("*NOTE particle system type has start-time [%f]\n",particleNode->getAttribute("start-time")->getFloatValue());
unitParticleSystemType->setEndTime(particleNode->getChild(i)->getAttribute("end-time")->getFloatValue());
} else if (particleNode->hasAttribute("end-time")) {
//printf("*NOTE particle system type has end-time [%f]\n",particleNode->getAttribute("end-time")->getFloatValue());
unitParticleSystemType->setEndTime(particleNode->getAttribute("end-time")->getFloatValue());
}
@ -504,11 +527,16 @@ void SkillType::load(const XmlNode *sn, const XmlNode *attackBoostsNode,
}
//sound
if(sn->hasChild("sound")) {
const XmlNode *soundNode= sn->getChild("sound");
vector<XmlNode *> soundNodeList = sn->getChildList("sound");
for(unsigned int i = 0; i < soundNodeList.size(); ++i) {
const XmlNode *soundNode= soundNodeList[i];
if(soundNode->getAttribute("enabled")->getBoolValue()) {
soundStartTime= soundNode->getAttribute("start-time")->getFloatValue();
sounds.resize((int)soundNode->getChildCount());
float soundStartTime= soundNode->getAttribute("start-time")->getFloatValue();
SkillSound *skillSound = new SkillSound();
skillSound->setStartTime(soundStartTime);
skillSound->getSoundContainer()->resize((int)soundNode->getChildCount());
skillSoundList.push_back(skillSound);
for(int i = 0; i < (int)soundNode->getChildCount(); ++i) {
const XmlNode *soundFileNode= soundNode->getChild("sound-file", i);
string path= soundFileNode->getAttribute("path")->getRestrictedValue(currentPath, true);
@ -516,7 +544,7 @@ void SkillType::load(const XmlNode *sn, const XmlNode *attackBoostsNode,
StaticSound *sound= new StaticSound();
sound->load(path);
loadedFileList[path].push_back(make_pair(parentLoader,soundFileNode->getAttribute("path")->getRestrictedValue()));
sounds[i]= sound;
(*skillSound->getSoundContainer())[i]= sound;
}
}
}
@ -743,7 +771,7 @@ void SkillType::saveGame(XmlNode *rootNode) {
//
// SoundContainer sounds;
// float soundStartTime;
skillTypeNode->addAttribute("soundStartTime",floatToStr(soundStartTime,6), mapTagReplacements);
// skillTypeNode->addAttribute("soundStartTime",floatToStr(soundStartTime,6), mapTagReplacements);
// RandomGen random;
skillTypeNode->addAttribute("random",intToStr(random.getLastNumber()), mapTagReplacements);
// AttackBoost attackBoost;
@ -806,7 +834,7 @@ AttackSkillType::AttackSkillType() {
splashRadius= 0;
spawnUnit="";
spawnUnitcount=0;
projectileParticleSystemType= NULL;
spawnUnitAtTarget=false;
splashParticleSystemType= NULL;
for(int i = 0; i < fieldCount; ++i) {
@ -821,8 +849,8 @@ AttackSkillType::AttackSkillType() {
}
AttackSkillType::~AttackSkillType() {
delete projectileParticleSystemType;
projectileParticleSystemType = NULL;
deleteValues(projectileTypes.begin(), projectileTypes.end());
delete splashParticleSystemType;
splashParticleSystemType = NULL;
@ -859,11 +887,16 @@ void AttackSkillType::load(const XmlNode *sn, const XmlNode *attackBoostsNode,
if (sn->hasChild("unit")) {
spawnUnit = sn->getChild("unit")->getAttribute("value")->getValue();
spawnUnitcount
= sn->getChild("unit")->getAttribute("amount")->getIntValue();
spawnUnitcount = sn->getChild("unit")->getAttribute("amount")->getIntValue();
if(sn->getChild("unit")->hasAttribute("spawnAtTarget")) {
spawnUnitAtTarget = sn->getChild("unit")->getAttribute("spawnAtTarget")->getBoolValue();
} else {
spawnUnitAtTarget = false;
}
} else {
spawnUnit = "";
spawnUnitcount = 0;
spawnUnitAtTarget = false;
}
//attack fields
const XmlNode *attackFieldsNode= sn->getChild("attack-fields");
@ -881,36 +914,81 @@ void AttackSkillType::load(const XmlNode *sn, const XmlNode *attackBoostsNode,
}
}
//projectile
const XmlNode *projectileNode= sn->getChild("projectile");
projectile= projectileNode->getAttribute("value")->getBoolValue();
if(projectile){
if(sn->hasChild("projectile")){
//projectile -- backward compatible old behaviour with only one projectile
const XmlNode *projectileNode= sn->getChild("projectile");
projectile= projectileNode->getAttribute("value")->getBoolValue();
if(projectile){
// create new projectile
ProjectileType *projectileType=new ProjectileType();
projectileTypes.push_back(projectileType);
projectileType->setAttackStartTime(attackStartTime);
projectileType->setDamagePercentage(100);
//proj particle
if(projectileNode->hasChild("particle")){
const XmlNode *particleNode= projectileNode->getChild("particle");
bool particleEnabled= particleNode->getAttribute("value")->getBoolValue();
if(particleEnabled){
string path= particleNode->getAttribute("path")->getRestrictedValue();
ParticleSystemTypeProjectile* projectileParticleSystemType= new ParticleSystemTypeProjectile();
projectileParticleSystemType->load(particleNode, dir, currentPath + path,
&Renderer::getInstance(), loadedFileList, parentLoader,
tt->getPath());
loadedFileList[currentPath + path].push_back(make_pair(parentLoader,particleNode->getAttribute("path")->getRestrictedValue()));
projectileType->setProjectileParticleSystemType(projectileParticleSystemType);
}
}
//proj sounds
const XmlNode *soundNode= projectileNode->getChild("sound");
if(soundNode->getAttribute("enabled")->getBoolValue()){
//proj particle
const XmlNode *particleNode= projectileNode->getChild("particle");
bool particleEnabled= particleNode->getAttribute("value")->getBoolValue();
if(particleEnabled){
string path= particleNode->getAttribute("path")->getRestrictedValue();
projectileParticleSystemType= new ParticleSystemTypeProjectile();
projectileParticleSystemType->load(particleNode, dir, currentPath + path,
&Renderer::getInstance(), loadedFileList, parentLoader,
tt->getPath());
projSounds.resize((int)soundNode->getChildCount());
for(int i=0; i < (int)soundNode->getChildCount(); ++i){
const XmlNode *soundFileNode= soundNode->getChild("sound-file", i);
string path= soundFileNode->getAttribute("path")->getRestrictedValue(currentPath, true);
//printf("\n\n\n\n!@#$ ---> parentLoader [%s] path [%s] nodeValue [%s] i = %d",parentLoader.c_str(),path.c_str(),soundFileNode->getAttribute("path")->getRestrictedValue().c_str(),i);
StaticSound *sound= new StaticSound();
sound->load(path);
loadedFileList[path].push_back(make_pair(parentLoader,soundFileNode->getAttribute("path")->getRestrictedValue()));
projSounds[i]= sound;
}
}
}
}
else {
const XmlNode *projectilesNode= sn->getChild("projectiles");
vector<XmlNode *> projectilesNodeList = projectilesNode->getChildList("projectile");
int totalDamagePercentage=0;
for(unsigned int i = 0; i < projectilesNodeList.size(); ++i) {
const XmlNode *projectileNode= projectilesNodeList[i];
ProjectileType *projectileType=new ProjectileType();
projectileType->load(projectileNode,dir, tt->getPath(), loadedFileList, parentLoader);
totalDamagePercentage += projectileType->getDamagePercentage();
projectileTypes.push_back(projectileType);
projectile=true;
}
//proj sounds
const XmlNode *soundNode= projectileNode->getChild("sound");
if(soundNode->getAttribute("enabled")->getBoolValue()){
if(totalDamagePercentage!=100){
throw megaglest_runtime_error("Damages percentages of projectiles don't sum up to 100 %");
}
projSounds.resize((int)soundNode->getChildCount());
for(int i=0; i < (int)soundNode->getChildCount(); ++i){
const XmlNode *soundFileNode= soundNode->getChild("sound-file", i);
string path= soundFileNode->getAttribute("path")->getRestrictedValue(currentPath, true);
//printf("\n\n\n\n!@#$ ---> parentLoader [%s] path [%s] nodeValue [%s] i = %d",parentLoader.c_str(),path.c_str(),soundFileNode->getAttribute("path")->getRestrictedValue().c_str(),i);
if(sn->hasChild("hitsound")==true){
//general hit sounds, individual ones can be set in projectiles
const XmlNode *soundNode= sn->getChild("hitsound");
if(soundNode->getAttribute("enabled")->getBoolValue()){
StaticSound *sound= new StaticSound();
sound->load(path);
loadedFileList[path].push_back(make_pair(parentLoader,soundFileNode->getAttribute("path")->getRestrictedValue()));
projSounds[i]= sound;
projSounds.resize((int)soundNode->getChildCount());
for(int i=0; i < (int)soundNode->getChildCount(); ++i){
const XmlNode *soundFileNode= soundNode->getChild("sound-file", i);
string path= soundFileNode->getAttribute("path")->getRestrictedValue(currentPath, true);
//printf("\n\n\n\n!@#$ ---> parentLoader [%s] path [%s] nodeValue [%s] i = %d",parentLoader.c_str(),path.c_str(),soundFileNode->getAttribute("path")->getRestrictedValue().c_str(),i);
StaticSound *sound= new StaticSound();
sound->load(path);
loadedFileList[path].push_back(make_pair(parentLoader,soundFileNode->getAttribute("path")->getRestrictedValue()));
projSounds[i]= sound;
}
}
}
}
@ -935,6 +1013,24 @@ void AttackSkillType::load(const XmlNode *sn, const XmlNode *attackBoostsNode,
}
}
int AttackSkillType::getTotalSpeed(const TotalUpgrade *totalUpgrade) const{
int result = speed + totalUpgrade->getAttackSpeed(this);
result = max(0,result);
return result;
}
// Get the amount to boost the attack animation speed by (based on attack-speed upgrades)
int AttackSkillType::getAnimSpeedBoost(const TotalUpgrade *totalUpgrade) const{
// Same calculation as in TotalUpgrade::sum, but bypassing the use of the value
// list (which is for the attack speed, not animation speed)
if(totalUpgrade->getAttackRangeIsMultiplier()) {
return animSpeed * (totalUpgrade->getAttackSpeed(NULL) / (double)100);
}
else {
return totalUpgrade->getAttackSpeed(NULL);
}
}
string AttackSkillType::toString(bool translatedValue) const{
if(translatedValue == false) {
return "Attack";
@ -983,12 +1079,15 @@ void AttackSkillType::saveGame(XmlNode *rootNode) {
attackSkillTypeNode->addAttribute("spawnUnit",spawnUnit, mapTagReplacements);
// int spawnUnitcount;
attackSkillTypeNode->addAttribute("spawnUnitcount",intToStr(spawnUnitcount), mapTagReplacements);
// bool spawnUnitAtTarget;
attackSkillTypeNode->addAttribute("spawnUnitAtTarget",intToStr(spawnUnitAtTarget), mapTagReplacements);
// bool projectile;
attackSkillTypeNode->addAttribute("projectile",intToStr(projectile), mapTagReplacements);
// ParticleSystemTypeProjectile* projectileParticleSystemType;
if(projectileParticleSystemType != NULL) {
projectileParticleSystemType->saveGame(attackSkillTypeNode);
}
// save a skill_type ????
// if(projectileParticleSystemType != NULL) {
// projectileParticleSystemType->saveGame(attackSkillTypeNode);
// }
// SoundContainer projSounds;
//
// bool splash;
@ -1262,6 +1361,15 @@ void DieSkillType::saveGame(XmlNode *rootNode) {
dieSkillTypeNode->addAttribute("fade",intToStr(fade), mapTagReplacements);
}
StaticSound *DieSkillType::getSound() const{
if(skillSoundList.size()==0){
return NULL;
}
else {
return skillSoundList.front()->getSoundContainer()->getRandSound();
}
}
// =====================================================
// class FogOfWarSkillType

View File

@ -27,6 +27,7 @@
#include "factory.h"
#include "sound_container.h"
#include "particle.h"
#include "projectile_type.h"
#include "upgrade_type.h"
#include "leak_dumper.h"
@ -74,6 +75,7 @@ enum SkillClass{
};
typedef list<UnitParticleSystemType*> UnitParticleSystemTypes;
typedef list<ProjectileType*> ProjectileTypes;
// =====================================================
// class SkillType
//
@ -123,8 +125,29 @@ public:
int toHp;
};
// =====================================================
// class SkillSound
// holds the start time and a SoundContainer
// =====================================================
class SkillSound{
private:
SoundContainer soundContainer;
float startTime;
public:
SkillSound();
~SkillSound();
SoundContainer *getSoundContainer() {return &soundContainer;}
float getStartTime() const {return startTime;}
void setStartTime(float value) {startTime=value;}
};
typedef list<SkillSound*> SkillSoundList;
class SkillType {
protected:
SkillClass skillClass;
string name;
@ -155,8 +178,7 @@ protected:
vector<Model *> animations;
vector<AnimationAttributes> animationAttributes;
SoundContainer sounds;
float soundStartTime;
SkillSoundList skillSoundList;
RandomGen random;
AttackBoost attackBoost;
@ -195,14 +217,14 @@ public:
int getSpeed() const {return speed;}
int getAnimSpeed() const {return animSpeed;}
Model *getAnimation(float animProgress=0, const Unit *unit=NULL, int *lastAnimationIndex=NULL, int *animationRandomCycleCount=NULL) const;
StaticSound *getSound() const {return sounds.getRandSound();}
float getSoundStartTime() const {return soundStartTime;}
float getShakeStartTime() const {return shakeStartTime;}
bool getShake() const {return shake;}
int getShakeIntensity() const {return shakeIntensity;}
int getShakeDuration() const {return shakeDuration;}
const SkillSoundList * getSkillSoundList() const {return &skillSoundList;}
bool getShakeSelfEnabled() const {return shakeSelfEnabled;}
bool getShakeSelfVisible() const {return shakeSelfVisible;}
bool getShakeSelfInCameraView() const {return shakeSelfInCameraView;}
@ -258,6 +280,8 @@ public:
// ===============================
class AttackSkillType: public SkillType{
public:
ProjectileTypes projectileTypes;
private:
int attackStrength;
int attackVar;
@ -268,8 +292,9 @@ private:
string spawnUnit;
int spawnUnitcount;
bool spawnUnitAtTarget;
bool projectile;
ParticleSystemTypeProjectile* projectileParticleSystemType;
//ParticleSystemTypeProjectile* projectileParticleSystemType;
SoundContainer projSounds;
bool splash;
@ -294,10 +319,10 @@ public:
inline float getAttackStartTime() const {return attackStartTime;}
inline string getSpawnUnit() const {return spawnUnit;}
inline int getSpawnUnitCount() const {return spawnUnitcount;}
inline bool getSpawnUnitAtTarget() const {return spawnUnitAtTarget;}
//get proj
inline bool getProjectile() const {return projectile;}
inline ParticleSystemTypeProjectile * getProjParticleType() const {return projectileParticleSystemType;}
inline StaticSound *getProjSound() const {return projSounds.getRandSound();}
//get splash
@ -309,6 +334,8 @@ public:
//misc
int getTotalAttackStrength(const TotalUpgrade *totalUpgrade) const;
int getTotalAttackRange(const TotalUpgrade *totalUpgrade) const;
virtual int getTotalSpeed(const TotalUpgrade *totalUpgrade) const;
virtual int getAnimSpeedBoost(const TotalUpgrade *totalUpgrade) const;
virtual void saveGame(XmlNode *rootNode);
};
@ -447,6 +474,7 @@ public:
virtual string toString(bool translatedValue) const;
virtual void saveGame(XmlNode *rootNode);
StaticSound *getSound() const;
};
// ===============================

View File

@ -89,6 +89,7 @@ UnitType::UnitType() : ProducibleType() {
lightColor= Vec3f(0.f);
light= false;
multiSelect= false;
commandable= true;
armorType= NULL;
rotatedBuildPos=0;
@ -125,7 +126,13 @@ UnitType::UnitType() : ProducibleType() {
epRegeneration= 0;
maxUnitCount= 0;
maxHp=0;
startHpValue=0;
startHpPercentage=1.0;
startHpType=stValue;
maxEp=0;
startEpValue=0;
startEpPercentage=0;
startEpType=stValue;
armor=0;
sight=0;
size=0;
@ -247,6 +254,59 @@ void UnitType::loaddd(int id,const string &dir, const TechTree *techTree,
}
addItemToVault(&(this->epRegeneration),this->epRegeneration);
// Check that we don't use both start-value and start-percentage, as they are mutually
// exclusive
if(parametersNode->getChild("max-hp")->hasAttribute("start-value") &&
parametersNode->getChild("max-hp")->hasAttribute("start-percentage")) {
throw megaglest_runtime_error("Unit " + name +
" has both start-value and start-percentage for HP", validationMode);
}
//startHpValue -- the *absolute* value to use for starting HP
if(parametersNode->getChild("max-hp")->hasAttribute("start-value")) {
//checkItemInVault(&(this->startEp),this->startEp);
startHpValue= parametersNode->getChild("max-hp")->getAttribute("start-value")->getIntValue();
startHpType= stValue;
}
addItemToVault(&(this->startHpValue),this->startHpValue);
//startHpPercentage -- the *relative* value to use for starting HP
if(parametersNode->getChild("max-hp")->hasAttribute("start-percentage")) {
startHpPercentage= parametersNode->getChild("max-hp")->getAttribute("start-percentage")->getIntValue();
startHpType= stPercentage;
}
// No start value set; use max HP before upgrades
if(!parametersNode->getChild("max-hp")->hasAttribute("start-value") &&
!parametersNode->getChild("max-hp")->hasAttribute("start-percentage")) {
startHpValue= parametersNode->getChild("max-hp")->getAttribute("value")->getIntValue();
startHpType= stValue;
}
addItemToVault(&(this->startHpPercentage),this->startHpPercentage);
// Check that we don't use both start-value and start-percentage, as they are mutually
// exclusive
if(parametersNode->getChild("max-ep")->hasAttribute("start-value") &&
parametersNode->getChild("max-ep")->hasAttribute("start-percentage")) {
throw megaglest_runtime_error("Unit " + name +
" has both start-value and start-percentage for EP", validationMode);
}
//startEpValue -- the *absolute* value to use for starting EP
if(parametersNode->getChild("max-ep")->hasAttribute("start-value")) {
//checkItemInVault(&(this->startEp),this->startEp);
startEpValue= parametersNode->getChild("max-ep")->getAttribute("start-value")->getIntValue();
startEpType= stValue;
}
addItemToVault(&(this->startEpValue),this->startEpValue);
//startEpPercentage -- the *relative* value to use for starting EP
if(parametersNode->getChild("max-ep")->hasAttribute("start-percentage")) {
startEpPercentage= parametersNode->getChild("max-ep")->getAttribute("start-percentage")->getIntValue();
startEpType= stPercentage;
}
addItemToVault(&(this->startEpPercentage),this->startEpPercentage);
//maxUnitCount
if(parametersNode->hasChild("max-unit-count")) {
//checkItemInVault(&(this->maxUnitCount),this->maxUnitCount);
@ -274,6 +334,10 @@ void UnitType::loaddd(int id,const string &dir, const TechTree *techTree,
//multi selection
multiSelect= parametersNode->getChild("multi-selection")->getAttribute("value")->getBoolValue();
//commandable
if(parametersNode->hasChild("commandable")){
commandable= parametersNode->getChild("commandable")->getAttribute("value")->getBoolValue();
}
//cellmap
allowEmptyCellMap = false;
const XmlNode *cellMapNode= parametersNode->getChild("cellmap");
@ -532,6 +596,65 @@ void UnitType::loaddd(int id,const string &dir, const TechTree *techTree,
}
}
sortedItems.clear();
hasDup = false;
// Lootable resources (resources given/lost on death)
if(parametersNode->hasChild("resources-death")) {
const XmlNode *deathResourcesNode= parametersNode->getChild("resources-death");
for(int i=0; i < deathResourcesNode->getChildCount(); ++i){
const XmlNode *resourceNode= deathResourcesNode->getChild("resource", i);
string name= resourceNode->getAttribute("name")->getRestrictedValue();
LootableResource resource;
resource.setResourceType(techTree->getResourceType(name));
// All attributes are optional, although nothing happens if they aren't used. They can
// be combined freely. Percentages will take affect before absolute values.
if(resourceNode->hasAttribute("amount-value")) {
resource.setAmountValue(resourceNode->getAttribute("amount-value")->getIntValue());
}
else {
resource.setAmountValue(0);
}
if(resourceNode->hasAttribute("amount-faction-percent")) {
resource.setAmountFactionPercent(resourceNode->getAttribute("amount-faction-percent")->getIntValue());
}
else {
resource.setAmountFactionPercent(0);
}
if(resourceNode->hasAttribute("loss-value")) {
resource.setLossValue(resourceNode->getAttribute("loss-value")->getIntValue());
}
else {
resource.setLossValue(0);
}
if(resourceNode->hasAttribute("loss-faction-percent")) {
resource.setLossFactionPercent(resourceNode->getAttribute("loss-faction-percent")->getIntValue());
}
else {
resource.setLossFactionPercent(0);
}
if(resourceNode->hasAttribute("allow-negative")) {
resource.setNegativeAllowed(resourceNode->getAttribute("allow-negative")->getBoolValue());
}
else {
resource.setNegativeAllowed(false);
}
// Figure out if there are duplicate resources. The value stored in the map is arbitrary,
// and exists solely because
if(std::find(lootableResources.begin(), lootableResources.end(), resource) != lootableResources.end()) {
printf("WARNING, unit type [%s] has one or more duplicate lootable resources\n", this->getName(false).c_str());
}
lootableResources.push_back(resource);
}
}
//image
const XmlNode *imageNode= parametersNode->getChild("image");
@ -1100,6 +1223,8 @@ std::string UnitType::toString() const {
result += " maxHp = " + intToStr(maxHp);
result += " hpRegeneration = " + intToStr(hpRegeneration);
result += " maxEp = " + intToStr(maxEp);
result += " startEpValue = " + intToStr(startEpValue);
result += " startEpPercentage = " + intToStr(startEpPercentage);
result += " epRegeneration = " + intToStr(epRegeneration);
result += " maxUnitCount = " + intToStr(getMaxUnitCount());
@ -1120,6 +1245,7 @@ std::string UnitType::toString() const {
result += " light = " + intToStr(light);
result += " lightColor = " + lightColor.getString();
result += " multiSelect = " + intToStr(multiSelect);
result += " commandable = " + intToStr(commandable);
result += " sight = " + intToStr(sight);
result += " size = " + intToStr(size);
result += " height = " + intToStr(height);

View File

@ -63,6 +63,45 @@ public:
static const Level * loadGame(const XmlNode *rootNode, const UnitType *ut);
};
// ===============================
// class LootResource
//
/// Stores information about a lootable resource. Lootable resources are stolen by the attacker on death.
// ===============================
class LootableResource {
private:
const ResourceType *type;
int amountValue;
int amountFactionPercent;
int lossValue;
int lossFactionPercent;
bool negativeAllowed;
public:
const ResourceType* getResourceType() const {return type;}
void setResourceType(const ResourceType *type) {this->type=type;}
int getAmountValue() const {return amountValue;}
void setAmountValue(int amountValue) {this->amountValue=amountValue;}
int getAmountFactionPercent() const {return amountFactionPercent;}
void setAmountFactionPercent(int amountPercentage) {this->amountFactionPercent=amountPercentage;}
int getLossValue() const {return lossValue;}
void setLossValue(int lossValue) {this->lossValue=lossValue;}
int getLossFactionPercent() const {return lossFactionPercent;}
void setLossFactionPercent(int lossPercentage) {this->lossFactionPercent=lossPercentage;}
bool isNegativeAllowed() const {return negativeAllowed;}
void setNegativeAllowed(bool negativeAllowed) {this->negativeAllowed=negativeAllowed;}
bool operator==(const LootableResource& other) {
return type == other.getResourceType();
}
};
// ===============================
// class UnitType
//
@ -92,6 +131,11 @@ public:
pCount
};
enum StartType {
stValue,
stPercentage
};
static const char *propertyNames[];
DamageParticleSystemTypes damageParticleSystemTypes;
private:
@ -99,13 +143,20 @@ private:
typedef vector<CommandType*> CommandTypes;
typedef vector<Resource> StoredResources;
typedef vector<Level> Levels;
typedef vector<LootableResource> LootableResources;
private:
//basic
int id;
int maxHp;
int startHpValue;
int startHpPercentage;
StartType startHpType;
int hpRegeneration;
int maxEp;
int startEpValue;
int startEpPercentage;
StartType startEpType;
int epRegeneration;
int maxUnitCount;
@ -120,6 +171,7 @@ private:
bool light;
Vec3f lightColor;
bool multiSelect;
bool commandable;
int sight;
int size; //size in cells
int renderSize; //size to render in cells
@ -140,6 +192,7 @@ private:
CommandTypes commandTypes;
StoredResources storedResources;
Levels levels;
LootableResources lootableResources;
//meeting point
bool meetingPoint;
@ -178,8 +231,14 @@ public:
inline int getId() const {return id;}
inline int getMaxHp() const {return maxHp;}
inline int getHpRegeneration() const {return hpRegeneration;}
inline int getStartHpValue() const {return startHpValue;}
inline int getStartHpPercentage() const {return startHpPercentage;}
inline StartType getStartHpType() const {return startHpType;}
inline int getMaxEp() const {return maxEp;}
inline int getEpRegeneration() const {return epRegeneration;}
inline int getStartEpValue() const {return startEpValue;}
inline int getStartEpPercentage() const {return startEpPercentage;}
inline StartType getStartEpType() const {return startEpType;}
inline int getMaxUnitCount() const {return maxUnitCount;}
inline bool getField(Field field) const {return fields[field];}
inline Field getField() const {return field;}
@ -197,12 +256,15 @@ public:
inline bool getRotationAllowed() const {return rotationAllowed;}
inline Vec3f getLightColor() const {return lightColor;}
inline bool getMultiSelect() const {return multiSelect;}
inline bool isCommandable() const {return commandable;}
inline int getSight() const {return sight;}
inline int getSize() const {return size;}
inline int getRenderSize() const {return renderSize;}
int getHeight() const {return height;}
int getStoredResourceCount() const {return (int)storedResources.size();}
inline const Resource *getStoredResource(int i) const {return &storedResources[i];}
int getLootableResourceCount() const {return lootableResources.size();}
inline const LootableResource getLootableResource(int i) const {return lootableResources.at(i);}
bool getCellMapCell(int x, int y, CardinalDir facing) const;
inline bool getMeetingPoint() const {return meetingPoint;}
inline bool getCountUnitDeathInStats() const {return countUnitDeathInStats;}

View File

@ -169,6 +169,19 @@ void UpgradeTypeBase::load(const XmlNode *upgradeNode, string upgradename) {
else {
prodSpeed = 0;
}
attackSpeedIsMultiplier = false;
if(upgradeNode->hasChild("attack-speed") == true) {
attackSpeed= upgradeNode->getChild("attack-speed")->getAttribute("value")->getIntValue();
if(upgradeNode->getChild("attack-speed")->getAttribute(VALUE_PERCENT_MULTIPLIER_KEY_NAME,false) != NULL) {
attackSpeedIsMultiplier = upgradeNode->getChild("attack-speed")->getAttribute(VALUE_PERCENT_MULTIPLIER_KEY_NAME)->getBoolValue();
//printf("Found prodSpeedIsMultiplier = %d\n",prodSpeedIsMultiplier);
}
}
else {
attackSpeed = 0;
}
}
int UpgradeTypeBase::getAttackStrength(const AttackSkillType *st) const {
@ -212,6 +225,20 @@ int UpgradeTypeBase::getMoveSpeed(const MoveSkillType *st) const {
}
}
int UpgradeTypeBase::getAttackSpeed(const AttackSkillType *st) const {
if(attackSpeedIsMultiplier == false || st == NULL) {
return attackSpeed;
}
else {
int result = 0;
if(attackSpeedIsMultiplierValueList.find(st->getName()) != attackSpeedIsMultiplierValueList.end()) {
result = attackSpeedIsMultiplierValueList.find(st->getName())->second;
}
return result;
}
}
int UpgradeTypeBase::getProdSpeed(const SkillType *st) const {
if(prodSpeedIsMultiplier == false || st == NULL) {
return prodSpeed;
@ -347,6 +374,18 @@ string UpgradeTypeBase::getDesc(bool translatedValue) const{
str+= indent+lang.getString("ProductionSpeed",(translatedValue == true ? "" : "english")) + " +" + intToStr(prodSpeed);
}
}
if(attackSpeed != 0) {
if(str != "") {
str += "\n";
}
if(attackSpeedIsMultiplier) {
str+= indent+lang.getString("AttackSpeed",(translatedValue == true ? "" : "english")) + " *" + intToStr(moveSpeed);
}
else {
str+= indent+lang.getString("AttackSpeed",(translatedValue == true ? "" : "english")) + " +" + intToStr(moveSpeed);
}
}
if(str != "") {
str += "\n";
}
@ -821,6 +860,9 @@ void TotalUpgrade::reset() {
prodSpeed=0;
prodSpeedIsMultiplier=false;
attackSpeed=0;
attackSpeedIsMultiplier=false;
}
void TotalUpgrade::sum(const UpgradeTypeBase *ut, const Unit *unit) {
@ -832,6 +874,7 @@ void TotalUpgrade::sum(const UpgradeTypeBase *ut, const Unit *unit) {
attackRangeIsMultiplier = ut->getAttackRangeIsMultiplier();
moveSpeedIsMultiplier = ut->getMoveSpeedIsMultiplier();
prodSpeedIsMultiplier = ut->getProdSpeedIsMultiplier();
attackSpeedIsMultiplier = ut->getAttackSpeedIsMultiplier();
if(ut->getMaxHpIsMultiplier() == true) {
//printf("#1 Maxhp maxHp = %d, unit->getHp() = %d ut->getMaxHp() = %d\n",maxHp,unit->getHp(),ut->getMaxHp());
@ -941,6 +984,19 @@ void TotalUpgrade::sum(const UpgradeTypeBase *ut, const Unit *unit) {
else {
prodSpeed += ut->getProdSpeed(NULL);
}
if(ut->getAttackSpeedIsMultiplier() == true) {
for(unsigned int i = 0; i < (unsigned int)unit->getType()->getSkillTypeCount(); ++i) {
const SkillType *skillType = unit->getType()->getSkillType(i);
const AttackSkillType *ast = dynamic_cast<const AttackSkillType *>(skillType);
if(ast != NULL) {
attackSpeedIsMultiplierValueList[ast->getName()] += ((double)ast->getSpeed() * ((double)ut->getAttackSpeed(NULL) / (double)100));
}
}
}
else {
attackSpeed += ut->getAttackSpeed(NULL);
}
}
void TotalUpgrade::apply(const UpgradeTypeBase *ut, const Unit *unit) {
@ -1080,6 +1136,23 @@ void TotalUpgrade::deapply(const UpgradeTypeBase *ut,const Unit *unit) {
prodSpeed -= ut->getProdSpeed(NULL);
enforceMinimumValue(0,prodSpeed);
}
if(ut->getAttackSpeedIsMultiplier() == true) {
for(unsigned int i = 0; i < (unsigned int)unit->getType()->getSkillTypeCount(); ++i) {
const SkillType *skillType = unit->getType()->getSkillType(i);
const AttackSkillType *ast = dynamic_cast<const AttackSkillType *>(skillType);
if(ast != NULL) {
attackSpeedIsMultiplierValueList[ast->getName()] -= ((double)ast->getSpeed() * ((double)ut->getAttackSpeed(NULL) / (double)100));
enforceMinimumValue(0, attackSpeedIsMultiplierValueList[ast->getName()]);
}
}
//printf("AFTER Applying moveSpeedIsMultiplier, moveSpeed = %d\n",moveSpeed);
}
else {
attackSpeed -= ut->getAttackSpeed(NULL);
enforceMinimumValue(0, attackSpeed);
}
}
void TotalUpgrade::incLevel(const UnitType *ut) {
@ -1184,6 +1257,16 @@ void TotalUpgrade::saveGame(XmlNode *rootNode) const {
prodSpeedMorphIsMultiplierValueListNode->addAttribute("key",iterMap->first, mapTagReplacements);
prodSpeedMorphIsMultiplierValueListNode->addAttribute("value",intToStr(iterMap->second), mapTagReplacements);
}
upgradeTypeBaseNode->addAttribute("attackSpeed",intToStr(attackSpeed), mapTagReplacements);
upgradeTypeBaseNode->addAttribute("attackSpeedIsMultiplier",intToStr(attackSpeedIsMultiplier), mapTagReplacements);
for(std::map<string,int>::const_iterator iterMap = attackSpeedIsMultiplierValueList.begin();
iterMap != attackSpeedIsMultiplierValueList.end(); ++iterMap) {
XmlNode *attackSpeedIsMultiplierValueListNode = upgradeTypeBaseNode->addChild("attackSpeedIsMultiplierValueList");
attackSpeedIsMultiplierValueListNode->addAttribute("key",iterMap->first, mapTagReplacements);
attackSpeedIsMultiplierValueListNode->addAttribute("value",intToStr(iterMap->second), mapTagReplacements);
}
}
void TotalUpgrade::loadGame(const XmlNode *rootNode) {
@ -1282,6 +1365,16 @@ void TotalUpgrade::loadGame(const XmlNode *rootNode) {
prodSpeedMorphIsMultiplierValueList[node->getAttribute("key")->getValue()] =
node->getAttribute("value")->getIntValue();
}
attackSpeed = upgradeTypeBaseNode->getAttribute("attackSpeed")->getIntValue();
attackSpeedIsMultiplier = upgradeTypeBaseNode->getAttribute("attackSpeedIsMultiplier")->getIntValue() != 0;
vector<XmlNode *> attackSpeedIsMultiplierValueNodeList = upgradeTypeBaseNode->getChildList("attackSpeedIsMultiplierValueList");
for(unsigned int i = 0; i < attackSpeedIsMultiplierValueNodeList.size(); ++i) {
XmlNode *node = attackSpeedIsMultiplierValueNodeList[i];
attackSpeedIsMultiplierValueList[node->getAttribute("key")->getValue()] =
node->getAttribute("value")->getIntValue();
}
}

View File

@ -9,6 +9,14 @@
// License, or (at your option) any later version
// ==============================================================
/**
* @file
* Classified the Upgrade type (which is sort of like a class for upgrades). Each upgrade has a
* type that details the stats that it boosts and the units that it affects. Also has TotalUpgrade,
* which is a sum of all upgrades applied to a particular unit (and is what determines how units
* stats are modified by an upgrade.
*/
#ifndef _GLEST_GAME_UPGRADETYPE_H_
#define _GLEST_GAME_UPGRADETYPE_H_
@ -39,10 +47,9 @@ class MoveSkillType;
class ProduceSkillType;
class Faction;
// ===============================
// class UpgradeTypeBase
// ===============================
/**
* Groups all information used for upgrades. Attack boosts also use this class for modifying stats.
*/
class UpgradeTypeBase {
protected:
string upgradename;
@ -64,23 +71,35 @@ protected:
int attackStrength;
bool attackStrengthIsMultiplier;
/**
* List of the values (for each skill type) that the stat was boosted by. This is used so
* that we can restore the original values when the upgrade is removed (eg, an attack
* boost wears off).
*/
std::map<string,int> attackStrengthMultiplierValueList;
int attackRange;
bool attackRangeIsMultiplier;
std::map<string,int> attackRangeMultiplierValueList;
std::map<string,int> attackRangeMultiplierValueList; /**< @see #attackStrengthMultiplierValueList */
int moveSpeed;
bool moveSpeedIsMultiplier;
std::map<string,int> moveSpeedIsMultiplierValueList;
std::map<string,int> moveSpeedIsMultiplierValueList; /**< @see #attackStrengthMultiplierValueList */
int prodSpeed;
bool prodSpeedIsMultiplier;
std::map<string,int> prodSpeedProduceIsMultiplierValueList;
std::map<string,int> prodSpeedUpgradeIsMultiplierValueList;
std::map<string,int> prodSpeedMorphIsMultiplierValueList;
std::map<string,int> prodSpeedProduceIsMultiplierValueList; /**< @see #attackStrengthMultiplierValueList */
std::map<string,int> prodSpeedUpgradeIsMultiplierValueList; /**< @see #attackStrengthMultiplierValueList */
std::map<string,int> prodSpeedMorphIsMultiplierValueList; /**< @see #attackStrengthMultiplierValueList */
int attackSpeed;
bool attackSpeedIsMultiplier;
std::map<string,int> attackSpeedIsMultiplierValueList;
public:
/**
* Creates an UpgradeTypeBase with values such that there are no stat changes.
*/
UpgradeTypeBase() {
maxHp = 0;;
maxHpIsMultiplier = false;
@ -127,11 +146,30 @@ public:
bool getMoveSpeedIsMultiplier() const {return moveSpeedIsMultiplier;}
int getProdSpeed(const SkillType *st) const;
bool getProdSpeedIsMultiplier() const {return prodSpeedIsMultiplier;}
int getAttackSpeed(const AttackSkillType *st) const;
bool getAttackSpeedIsMultiplier() const {return attackSpeedIsMultiplier;}
/**
* Loads the upgrade values (stat boosts and whether or not the boosts use a multiplier) from an
* XML node.
* @param upgradeNode Node containing the stat boost elements (`max-hp`, `attack-strength`, etc).
* @param upgradename Unique identifier for the upgrade.
*/
void load(const XmlNode *upgradeNode, string upgradename);
/**
* Creates a string representation of the upgrade. All stat boosts are detailed on their own line
* with their corresponding boosts.
* @param translatedValue If true, the description is translated. Otherwise the description uses
* names as they appear in the XMLs.
*/
virtual string getDesc(bool translatedValue) const;
/**
* Returns a string representation of this object. Lists all the value that the object stores.
* For debugging purposes, only.
*/
std::string toString() const {
std::string result = "";
@ -163,9 +201,14 @@ public:
return result;
}
// TODO: It's not clear if these save game methods are being used, currently. I think
// attack boosts might use the few lines that aren't commented out.
virtual void saveGame(XmlNode *rootNode) const;
static const UpgradeType * loadGame(const XmlNode *rootNode, Faction *faction);
/**
* Generates a checksum value for the upgrade.
*/
Checksum getCRC() {
Checksum crcForUpgradeType;
@ -207,58 +250,145 @@ public:
crcForUpgradeType.addInt64((int64)prodSpeedUpgradeIsMultiplierValueList.size());
//std::map<string,int> prodSpeedMorphIsMultiplierValueList;
crcForUpgradeType.addInt64((int64)prodSpeedMorphIsMultiplierValueList.size());
crcForUpgradeType.addInt(attackSpeed);
crcForUpgradeType.addInt(attackSpeedIsMultiplier);
return crcForUpgradeType;
}
};
// ===============================
// class UpgradeType
// ===============================
/**
* Represents the type of upgrade. That is, the single upgrade as it appears in the faction's XML
* files. Each upgrade has a single `UpgradeType`. Contains information about what units are
* affected by the upgrade.
*/
class UpgradeType: public UpgradeTypeBase, public ProducibleType {
private:
/**
* List of unit types (the "classes" of units, eg, swordman) that are affected by this upgrade.
*/
vector<const UnitType*> effects;
public:
/**
* Sets the upgrade name to the directory name (the base name of `dir`).
* @param dir Path of the upgrade directory.
*/
void preLoad(const string &dir);
/**
* Loads an upgrade from an XML file.
* @param dir Path of the upgrade directory. The file name is determined from this.
* @param techTree The techtree that this upgrade is in. Used to access the common data
* directory and to access resources.
* @param factionType The faction type (a unique type for each faction) that the upgrade belongs
* to. Used for accessing unit types that are in the unit requirements list.
* @param checksum Will have the checksum of the upgrade path added to it (treated the same way
* as the `techtreeChecksum`).
* @param techtreeChecksum Cumulative checksum for the techtree. The path of loaded upgrades
* is added to this checksum.
*/
void load(const string &dir, const TechTree *techTree,
const FactionType *factionType, Checksum* checksum,
Checksum* techtreeChecksum,
std::map<string,vector<pair<string, string> > > &loadedFileList,
bool validationMode=false);
/**
* Obtains the upgrade name.
* @param translatedValue If true, the name is translated. Otherwise the name is returned as it
* appears in the XMLs.
*/
virtual string getName(bool translatedValue=false) const;
//get all
/**
* Returns the number of UnitTypes affected by this upgrade.
*/
int getEffectCount() const {return (int)effects.size();}
/**
* Returns a particular unit type affected by this upgrade.
* @param i Index of the unit type in the #effects list.
*/
const UnitType * getEffect(int i) const {return effects[i];}
/**
* Determines if a unit is affected by this upgrade.
* @param unitType The UnitType we are checking (to see if they're affected).
* @return True if the unit is affected, false otherwise.
*/
bool isAffected(const UnitType *unitType) const;
//other methods
/**
* Creates a description for this upgrade. Lists the affected units.
*/
virtual string getReqDesc(bool translatedValue) const;
//virtual void saveGame(XmlNode *rootNode) const;
//virtual void loadGame(const XmlNode *rootNode);
};
// ===============================
// class TotalUpgrade
// ===============================
/**
* Keeps track of the cumulative effects of upgrades on units. This allows us to apply multiple
* upgrades to a unit with the effects stacking.
*/
class TotalUpgrade: public UpgradeTypeBase {
public:
TotalUpgrade();
virtual ~TotalUpgrade() {}
/**
* Resets all stat boosts (so there's effectively no upgrade).
*/
void reset();
/**
* Adds an upgrade to this one, stacking the effects. Note that multipliers are stacked
* by multiplying by the original, unboosted amount, and then adding that to the TotalUpgrade.
* @param ut The upgrade to apply.
* @param unit The unit this TotalUpgrade is associated with (since when we use a multiplier,
* the stats raise by an amount relative to the unit's base stats).
*/
void sum(const UpgradeTypeBase *ut, const Unit *unit);
/**
* Increases the level of the unit. Doing so results in their HP, EP, and armour going up by
* 50% while their sight goes up by 20%.
* @param ut The unit type to get the original stats from (so we can determine just how much
* to increase the stats by on level up).
*/
void incLevel(const UnitType *ut);
/**
* Applies the upgrade. Just a delegate to TotalUpgrade::sum.
*/
void apply(const UpgradeTypeBase *ut, const Unit *unit);
/**
* Removes the effect of an upgrade to a specific unit. Using this after applying the upgrade
* is an invariant. ie,
*
* totalUpgrade->apply(upgrade, unit);
* totalUpgrade->deapply(upgrade, unit);
* // totalUpgrade is now the same as before the call to apply()
*
* @param ut The upgrade to remove.
* @param unit The unit this TotalUpgrade is associated with (since when we use a multiplier,
* the stats were raise by an amount relative to the unit's base stats).
*/
void deapply(const UpgradeTypeBase *ut, const Unit *unit);
/**
* Creates the XML for the save game file. Essentially just stores everything about its state.
* @rootNode The node of the unit that this TotalUpgrade object belongs to.
*/
void saveGame(XmlNode *rootNode) const;
/**
* Reloads the object's state from a saved game.
* @rootNode The node of the unit that this TotalUpgrade object belongs to.
*/
void loadGame(const XmlNode *rootNode);
};

View File

@ -78,6 +78,7 @@ Checksum Scenario::load(const string &path) {
//parse xml
XmlTree xmlTree;
xmlTree.setSkipUpdatePathClimbingParts(true);
xmlTree.load(path,Properties::getTagReplacementValues());
const XmlNode *scenarioNode= xmlTree.getRootNode();
const XmlNode *scriptsNode= scenarioNode->getChild("scripts");

View File

@ -21,6 +21,7 @@
#include "network_manager.h"
#include "object.h"
#include "particle_type.h"
#include "projectile_type.h"
#include "path_finder.h"
#include "renderer.h"
#include "sound.h"
@ -127,16 +128,18 @@ bool UnitUpdater::updateUnit(Unit *unit) {
//play skill sound
const SkillType *currSkill= unit->getCurrSkill();
if(currSkill->getSound() != NULL) {
float soundStartTime= currSkill->getSoundStartTime();
for(SkillSoundList::const_iterator it= currSkill->getSkillSoundList()->begin(); it != currSkill->getSkillSoundList()->end(); ++it) {
float soundStartTime= (*it)->getStartTime();
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());
soundRenderer.playFx((*it)->getSoundContainer()->getRandSound(), unit->getCurrVector(), gameCamera->getPos());
}
}
}
if (currSkill->getShake()) {
float shakeStartTime = currSkill->getShakeStartTime();
if (shakeStartTime >= unit->getLastAnimProgressAsFloat()
@ -186,14 +189,24 @@ bool UnitUpdater::updateUnit(Unit *unit) {
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);
bool startAttackParticleSystemNow = false;
if(ast->projectileTypes.empty() == true ){
startAttackParticleSystemNow = (attackStartTime >= lastAnimProgress && attackStartTime < animProgress);
}
else {// start projectile attack
for(ProjectileTypes::const_iterator it= ast->projectileTypes.begin(); it != ast->projectileTypes.end(); ++it) {
attackStartTime= (*it)->getAttackStartTime();
startAttackParticleSystemNow = (attackStartTime >= lastAnimProgress && attackStartTime < animProgress);
if(startAttackParticleSystemNow==true) break;
}
}
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);
startAttackParticleSystem(unit,lastAnimProgress,animProgress);
}
}
@ -257,55 +270,12 @@ bool UnitUpdater::updateUnit(Unit *unit) {
else if(unit->getCommandSize() > 0) {
Command *command= unit->getCurrCommand();
if(command != NULL) {
const CommandType *ct = command->getCommandType();
const AttackCommandType *act= dynamic_cast<const AttackCommandType*>(command->getCommandType());
if( act != NULL && act->getAttackSkillType() != NULL &&
act->getAttackSkillType()->getSpawnUnit() != "" && act->getAttackSkillType()->getSpawnUnitCount() > 0) {
const FactionType *ft= unit->getFaction()->getType();
const UnitType *spawnUnitType = ft->getUnitType(act->getAttackSkillType()->getSpawnUnit());
int spawnCount = act->getAttackSkillType()->getSpawnUnitCount();
for (int y=0; y < spawnCount; ++y) {
if(spawnUnitType->getMaxUnitCount() > 0) {
if(spawnUnitType->getMaxUnitCount() <= unit->getFaction()->getCountForMaxUnitCount(spawnUnitType)) {
break;
}
}
UnitPathInterface *newpath = NULL;
switch(this->game->getGameSettings()->getPathFinderType()) {
case pfBasic:
newpath = new UnitPathBasic();
break;
default:
throw megaglest_runtime_error("detected unsupported pathfinder type!");
}
Unit *spawned= new Unit(world->getNextUnitId(unit->getFaction()), newpath,
Vec2i(0), spawnUnitType, unit->getFaction(),
world->getMap(), CardinalDir::NORTH);
//SystemFlags::OutputDebug(SystemFlags::debugUnitCommands,"In [%s::%s Line: %d] about to place unit for unit [%s]\n",__FILE__,__FUNCTION__,__LINE__,spawned->toString().c_str());
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());
}
}
if (act != NULL && act->getAttackSkillType() != NULL
&& act->getAttackSkillType()->getSpawnUnit() != ""
&& act->getAttackSkillType()->getSpawnUnitCount() > 0) {
spawnAttack(unit,act->getAttackSkillType()->getSpawnUnit(),act->getAttackSkillType()->getSpawnUnitCount(),act->getAttackSkillType()->getSpawnUnitAtTarget());
}
}
}
@ -343,6 +313,65 @@ bool UnitUpdater::updateUnit(Unit *unit) {
return processUnitCommand;
}
void UnitUpdater::spawnAttack(Unit *unit,string spawnUnit,int spawnUnitcount,bool spawnUnitAtTarget,Vec2i targetPos) {
if(spawnUnit != "" && spawnUnitcount > 0) {
const FactionType *ft= unit->getFaction()->getType();
const UnitType *spawnUnitType = ft->getUnitType(spawnUnit);
int spawnCount = spawnUnitcount;
for (int y=0; y < spawnCount; ++y) {
if(spawnUnitType->getMaxUnitCount() > 0) {
if(spawnUnitType->getMaxUnitCount() <= unit->getFaction()->getCountForMaxUnitCount(spawnUnitType)) {
break;
}
}
UnitPathInterface *newpath = NULL;
switch(this->game->getGameSettings()->getPathFinderType()) {
case pfBasic:
newpath = new UnitPathBasic();
break;
default:
throw megaglest_runtime_error("detected unsupported pathfinder type!");
}
Unit *spawned= new Unit(world->getNextUnitId(unit->getFaction()), newpath,
Vec2i(0), spawnUnitType, unit->getFaction(),
world->getMap(), CardinalDir::NORTH);
//SystemFlags::OutputDebug(SystemFlags::debugUnitCommands,"In [%s::%s Line: %d] about to place unit for unit [%s]\n",__FILE__,__FUNCTION__,__LINE__,spawned->toString().c_str());
bool placedSpawnUnit=false;
if(targetPos==Vec2i(-10,-10)) {
targetPos=unit->getTargetPos();
}
if(spawnUnitAtTarget) {
placedSpawnUnit=world->placeUnit(targetPos, 10, spawned);
} else {
placedSpawnUnit=world->placeUnit(unit->getCenteredPos(), 10, spawned);
}
if(!placedSpawnUnit) {
//SystemFlags::OutputDebug(SystemFlags::debugUnitCommands,"In [%s::%s Line: %d] COULD NOT PLACE UNIT for unitID [%d]\n",__FILE__,__FUNCTION__,__LINE__,spawned->getId());
// This will also cleanup newPath
delete spawned;
spawned = NULL;
}
else {
spawned->create();
spawned->born(NULL);
world->getStats()->produce(unit->getFactionIndex(),spawned->getType()->getCountUnitProductionInStats());
const CommandType *ct= spawned->getType()->getFirstAttackCommand(unit->getTargetField());
if(ct == NULL){
ct= spawned->computeCommandType(targetPos,map->getCell(targetPos)->getUnit(unit->getTargetField()));
}
if(ct != NULL){
if(SystemFlags::getSystemSettingType(SystemFlags::debugUnitCommands).enabled) SystemFlags::OutputDebug(SystemFlags::debugUnitCommands,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
spawned->giveCommand(new Command(ct, targetPos));
}
scriptManager->onUnitCreated(spawned);
}
}
}
}
// ==================== progress commands ====================
//VERY IMPORTANT: compute next state depending on the first order of the list
@ -2488,10 +2517,10 @@ void UnitUpdater::updateSwitchTeam(Unit *unit, int frameIndex) {
// ==================== attack ====================
void UnitUpdater::hit(Unit *attacker){
hit(attacker, dynamic_cast<const AttackSkillType*>(attacker->getCurrSkill()), attacker->getTargetPos(), attacker->getTargetField());
hit(attacker, dynamic_cast<const AttackSkillType*>(attacker->getCurrSkill()), attacker->getTargetPos(), attacker->getTargetField(),100);
}
void UnitUpdater::hit(Unit *attacker, const AttackSkillType* ast, const Vec2i &targetPos, Field targetField){
void UnitUpdater::hit(Unit *attacker, const AttackSkillType* ast, const Vec2i &targetPos, Field targetField, int damagePercent){
//hit attack positions
if(ast != NULL && ast->getSplash()) {
char szBuf[8096]="";
@ -2511,7 +2540,7 @@ void UnitUpdater::hit(Unit *attacker, const AttackSkillType* ast, const Vec2i &t
float distance = pci.getPos().dist(targetPos);
distance = truncateDecimal<float>(distance,6);
damage(attacker, ast, attacked, distance);
damage(attacker, ast, attacked, distance,damagePercent);
}
}
}
@ -2524,12 +2553,12 @@ void UnitUpdater::hit(Unit *attacker, const AttackSkillType* ast, const Vec2i &t
attacker->addNetworkCRCDecHp(szBuf);
if(attacked != NULL) {
damage(attacker, ast, attacked, 0.f);
damage(attacker, ast, attacked, 0.f,damagePercent);
}
}
}
void UnitUpdater::damage(Unit *attacker, const AttackSkillType* ast, Unit *attacked, float distance) {
void UnitUpdater::damage(Unit *attacker, const AttackSkillType* ast, Unit *attacked, float distance, int damagePercent) {
if(attacker == NULL) {
throw megaglest_runtime_error("attacker == NULL");
}
@ -2555,6 +2584,7 @@ void UnitUpdater::damage(Unit *attacker, const AttackSkillType* ast, Unit *attac
damage *= damageMultiplier;
damage = truncateDecimal<float>(damage,6);
damage = (damage*damagePercent)/100;
if(damage < 1) {
damage= 1;
}
@ -2573,6 +2603,37 @@ void UnitUpdater::damage(Unit *attacker, const AttackSkillType* ast, Unit *attac
attacker->incKills(attacked->getTeam());
}
// Perform resource looting iff the attack is from a different faction
if(attacker->getFaction() != attacked->getFaction()) {
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(), -(factionTotalResource * resource.getLossFactionPercent() / 100));
attacked->getFaction()->incResourceAmount(resource.getResourceType(), -resource.getLossValue());
attacker->getFaction()->incResourceAmount(resource.getResourceType(), factionTotalResource * resource.getAmountFactionPercent() / 100);
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(), -(std::min)(factionTotalResource * resource.getLossFactionPercent() / 100, factionTotalResource));
attacked->getFaction()->incResourceAmount(resource.getResourceType(), -(std::min)(resource.getLossValue(), factionTotalResource));
attacker->getFaction()->incResourceAmount(resource.getResourceType(), (std::min)(factionTotalResource * resource.getAmountFactionPercent() / 100, factionTotalResource));
attacker->getFaction()->incResourceAmount(resource.getResourceType(), (std::min)(resource.getAmountValue(), factionTotalResource));
}
}
}
switch(this->game->getGameSettings()->getPathFinderType()) {
case pfBasic:
break;
@ -2592,18 +2653,18 @@ void UnitUpdater::damage(Unit *attacker, const AttackSkillType* ast, Unit *attac
//attacker->computeHp();
}
void UnitUpdater::startAttackParticleSystem(Unit *unit){
void UnitUpdater::startAttackParticleSystem(Unit *unit, float lastAnimProgress, float animProgress){
Renderer &renderer= Renderer::getInstance();
ProjectileParticleSystem *psProj = 0;
//const AttackSkillType *ast= dynamic_cast<const AttackSkillType*>(unit->getCurrSkill());
const AttackSkillType *ast= static_cast<const AttackSkillType*>(unit->getCurrSkill());
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();
ParticleSystemTypeSplash *pstSplash= ast->getSplashParticleType();
bool hasProjectile = !ast->projectileTypes.empty();
Vec3f startPos= unit->getCurrVector();
Vec3f endPos= unit->getTargetVec();
@ -2615,39 +2676,51 @@ void UnitUpdater::startAttackParticleSystem(Unit *unit){
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));
//for(ProjectileParticleSystemTypes::const_iterator pit= unit->getCurrSkill()->projectileParticleSystemTypes.begin(); pit != unit->getCurrSkill()->projectileParticleSystemTypes.end(); ++pit) {
for(ProjectileTypes::const_iterator pt= ast->projectileTypes.begin(); pt != ast->projectileTypes.end(); ++pt) {
bool startAttackParticleSystemNow = ((*pt)->getAttackStartTime() >= lastAnimProgress && (*pt)->getAttackStartTime() < animProgress);
if(startAttackParticleSystemNow){
ProjectileParticleSystem *psProj= (*pt)->getProjectileParticleSystemType()->create(unit);
psProj->setPath(startPos, endPos);
psProj->setObserver(new ParticleDamager(unit,(*pt), 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);
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);
unit->addAttackParticleSystem(psSplash);
psProj->link(psSplash);
}
}
renderer.manageParticleSystem(psProj, rsGame);
unit->addAttackParticleSystem(psProj);
}
else {
// if no projectile, still deal damage..
if(hasProjectile == false) {
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));
//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);
unit->addAttackParticleSystem(psSplash);
}
renderer.manageParticleSystem(psSplash, rsGame);
if(pstProj!=NULL){
psProj->link(psSplash);
}
unit->addAttackParticleSystem(psSplash);
}
}
@ -3204,9 +3277,10 @@ void UnitUpdater::loadGame(const XmlNode *rootNode) {
// class ParticleDamager
// =====================================================
ParticleDamager::ParticleDamager(Unit *attacker, UnitUpdater *unitUpdater, const GameCamera *gameCamera){
ParticleDamager::ParticleDamager(Unit *attacker,const ProjectileType* projectileType, UnitUpdater *unitUpdater, const GameCamera *gameCamera){
this->gameCamera= gameCamera;
this->attackerRef= attacker;
this->projectileType= projectileType;
this->ast= static_cast<const AttackSkillType*>(attacker->getCurrSkill());
this->targetPos= attacker->getTargetPos();
this->targetField= attacker->getTargetField();
@ -3223,17 +3297,45 @@ void ParticleDamager::update(ParticleSystem *particleSystem) {
snprintf(szBuf,8095,"Unit hitting [ParticleDamager::update] [%s] targetField = %d",targetPos.getString().c_str(),targetField);
attacker->addNetworkCRCDecHp(szBuf);
unitUpdater->hit(attacker, ast, targetPos, targetField);
unitUpdater->hit(attacker, ast, targetPos, targetField, projectileType->getDamagePercentage());
//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();
// Try to use the sound form the projetileType
StaticSound *projSound=projectileType->getHitSound();
if(projSound == NULL){
// use the sound from the skill
projSound= ast->getProjSound();
}
if(particleSystem->getVisible() && projSound != NULL) {
SoundRenderer::getInstance().playFx(projSound, attacker->getCurrVector(), gameCamera->getPos());
}
//check for spawnattack
if(projectileType->getSpawnUnit()!="" && projectileType->getSpawnUnitcount()>0 ){
unitUpdater->spawnAttack(attacker,projectileType->getSpawnUnit(),projectileType->getSpawnUnitcount(),projectileType->getSpawnUnitAtTarget(),targetPos);
}
// check for shake and shake
if(projectileType->isShake()==true){
World *world=attacker->getFaction()->getWorld();
Map* map=world->getMap();
Game *game=world->getGame();
//Unit *attacked= map->getCell(targetPos)->getUnit(targetField);
Vec2i surfaceTargetPos=Map::toSurfCoords(targetPos);
bool visibility=(!projectileType->isShakeVisible())||(map->getSurfaceCell(surfaceTargetPos)->isVisible(world->getThisTeamIndex()) ||
(game->getWorld()->showWorldForPlayer(game->getWorld()->getThisTeamIndex()) == true));
bool isInCameraView=(!projectileType->isShakeInCameraView()) || Renderer::getInstance().posInCellQuadCache(surfaceTargetPos).first;
if(visibility && isInCameraView) {
game->getGameCameraPtr()->shake( projectileType->getShakeDuration(), projectileType->getShakeIntensity(),projectileType->isShakeCameraDistanceAffected(),map->getSurfaceCell(surfaceTargetPos)->getVertex());
}
}
}
particleSystem->setObserver(NULL);
delete this;

View File

@ -103,6 +103,7 @@ public:
//update skills
bool updateUnit(Unit *unit);
void spawnAttack(Unit *unit,string spawnUnit,int spawnUnitcount,bool spawnUnitAtTarget,Vec2i targetPos=Vec2i(-10,-10));
//update commands
void updateUnitCommand(Unit *unit, int frameIndex);
@ -141,9 +142,9 @@ public:
private:
//attack
void hit(Unit *attacker);
void hit(Unit *attacker, const AttackSkillType* ast, const Vec2i &targetPos, Field targetField);
void damage(Unit *attacker, const AttackSkillType* ast, Unit *attacked, float distance);
void startAttackParticleSystem(Unit *unit);
void hit(Unit *attacker, const AttackSkillType* ast, const Vec2i &targetPos, Field targetField, int damagePercent);
void damage(Unit *attacker, const AttackSkillType* ast, Unit *attacked, float distance, int damagePercent);
void startAttackParticleSystem(Unit *unit, float lastAnimProgress, float animProgress);
//misc
bool searchForResource(Unit *unit, const HarvestCommandType *hct);
@ -169,13 +170,14 @@ class ParticleDamager: public ParticleObserver {
public:
UnitReference attackerRef;
const AttackSkillType* ast;
const ProjectileType* projectileType;
UnitUpdater *unitUpdater;
const GameCamera *gameCamera;
Vec2i targetPos;
Field targetField;
public:
ParticleDamager(Unit *attacker, UnitUpdater *unitUpdater, const GameCamera *gameCamera);
ParticleDamager(Unit *attacker, const ProjectileType *projectileType, UnitUpdater *unitUpdater, const GameCamera *gameCamera);
virtual void update(ParticleSystem *particleSystem);
virtual void saveGame(XmlNode *rootNode);

View File

@ -49,6 +49,8 @@ public:
Vec3f pos;
Vec3f lastPos;
Vec3f speed;
float speedUpRelative;
Vec3f speedUpConstant;
Vec3f accel;
Vec4f color;
float size;
@ -147,6 +149,8 @@ protected:
int varParticleEnergy;
float particleSize;
float speed;
float speedUpRelative;
float speedUpConstant;
Vec3f factionColor;
bool teamcolorNoEnergy;
bool teamcolorEnergy;
@ -192,6 +196,8 @@ public:
void setVarParticleEnergy(int varParticleEnergy);
void setParticleSize(float particleSize);
void setSpeed(float speed);
void setSpeedUpRelative(float speedUpRelative);
void setSpeedUpConstant(float speedUpConstant);
virtual void setActive(bool active);
void setObserver(ParticleObserver *particleObserver);
virtual void setVisible(bool visible);

View File

@ -227,7 +227,7 @@ bool EndsWith(const string &str, const string& key);
void endPathWithSlash(string &path, bool requireOSSlash=false);
void trimPathWithStartingSlash(string &path);
void updatePathClimbingParts(string &path);
void updatePathClimbingParts(string &path,bool processPreviousDirTokenCheck=true);
string formatPath(string path);
string replaceAllHTMLEntities(string& context);

View File

@ -100,10 +100,10 @@ public:
bool hasString(const string &key) const;
static bool applyTagsToValue(string &value, const std::map<string,string> *mapTagReplacementValues=NULL);
static bool applyTagsToValue(string &value, const std::map<string,string> *mapTagReplacementValues=NULL, bool skipUpdatePathClimbingParts=false);
static std::map<string,string> getTagReplacementValues(std::map<string,string> *mapExtraTagReplacementValues=NULL);
static bool isValuePathVariable(const string &value);
static void updateValuePathVariable(string &value);
static void updateValuePathVariable(string &value, bool skipUpdatePathClimbingParts=false);
string getpath() const { return path;}

View File

@ -124,7 +124,7 @@ public:
static bool isInitialized();
void cleanup();
XmlNode *load(const string &path, const std::map<string,string> &mapTagReplacementValues,bool noValidation=false,bool skipStackTrace=false);
XmlNode *load(const string &path, const std::map<string,string> &mapTagReplacementValues,bool noValidation=false,bool skipStackTrace=false,bool skipUpdatePathClimbingParts=false);
void save(const string &path, const XmlNode *node);
};
@ -138,6 +138,7 @@ private:
string loadPath;
xml_engine_parser_type engine_type;
bool skipStackCheck;
bool skipUpdatePathClimbingParts;
private:
XmlTree(XmlTree&);
void operator =(XmlTree&);
@ -147,6 +148,7 @@ public:
XmlTree(xml_engine_parser_type engine_type = XML_RAPIDXML_ENGINE);
~XmlTree();
void setSkipUpdatePathClimbingParts(bool value);
void init(const string &name);
void load(const string &path, const std::map<string,string> &mapTagReplacementValues, bool noValidation=false,bool skipStackCheck=false,bool skipStackTrace=false);
void save(const string &path);
@ -182,7 +184,7 @@ public:
#endif
XmlNode(xml_node<> *node, const std::map<string,string> &mapTagReplacementValues);
XmlNode(xml_node<> *node, const std::map<string,string> &mapTagReplacementValues,bool skipUpdatePathClimbingParts=false);
XmlNode(const string &name);
~XmlNode();

View File

@ -50,6 +50,10 @@ void Particle::saveGame(XmlNode *rootNode) {
particleNode->addAttribute("lastPos",lastPos.getString(), mapTagReplacements);
// Vec3f speed;
particleNode->addAttribute("speed",speed.getString(), mapTagReplacements);
// Vec3f speedUpRelative;
particleNode->addAttribute("speedUpRelative",floatToStr(speedUpRelative,6), mapTagReplacements);
// Vec3f speedUpConstant;
particleNode->addAttribute("speedUpConstant",speedUpConstant.getString(), mapTagReplacements);
// Vec3f accel;
particleNode->addAttribute("accel",accel.getString(), mapTagReplacements);
// Vec4f color;
@ -70,6 +74,10 @@ void Particle::loadGame(const XmlNode *rootNode) {
lastPos = Vec3f::strToVec3(particleNode->getAttribute("lastPos")->getValue());
// Vec3f speed;
speed = Vec3f::strToVec3(particleNode->getAttribute("speed")->getValue());
// Vec3f speed;
speedUpRelative = particleNode->getAttribute("speedUpRelative")->getFloatValue();
// Vec3f speed;
speedUpConstant = Vec3f::strToVec3(particleNode->getAttribute("speedUpConstant")->getValue());
// Vec3f accel;
accel = Vec3f::strToVec3(particleNode->getAttribute("accel")->getValue());
// Vec4f color;
@ -290,6 +298,16 @@ void ParticleSystem::setSpeed(float speed){
this->speed = truncateDecimal<float>(this->speed,6);
}
void ParticleSystem::setSpeedUpRelative(float speedUpRelative){
this->speedUpRelative= speedUpRelative;
this->speedUpRelative = truncateDecimal<float>(this->speedUpRelative,6);
}
void ParticleSystem::setSpeedUpConstant(float speedUpConstant){
this->speedUpConstant= speedUpConstant;
this->speedUpConstant = truncateDecimal<float>(this->speedUpConstant,6);
}
void ParticleSystem::setActive(bool active){
this->active= active;
for(int i=getChildCount()-1; i>=0; i--)
@ -1114,6 +1132,7 @@ void UnitParticleSystem::initParticle(Particle *p, int particleIndex){
p->lastPos= pos;
oldPosition= pos;
p->size= particleSize;
p->speedUpRelative= speedUpRelative;
p->accel= Vec3f(0.0f, -gravity, 0.0f);
p->accel.x = truncateDecimal<float>(p->accel.x,6);
p->accel.y = truncateDecimal<float>(p->accel.y,6);
@ -1228,6 +1247,8 @@ void UnitParticleSystem::initParticle(Particle *p, int particleIndex){
} break;
default: throw megaglest_runtime_error("bad shape");
}
//need to do that down here because we need p->speed for it.
p->speedUpConstant= Vec3f(speedUpConstant)*p->speed;
}
void UnitParticleSystem::update(){
@ -1299,6 +1320,8 @@ void UnitParticleSystem::updateParticle(Particle *p){
p->pos.z = truncateDecimal<float>(p->pos.z,6);
}
p->speed += p->accel;
p->speed += p->speedUpConstant;
p->speed=p->speed*(1+p->speedUpRelative);
p->speed.x = truncateDecimal<float>(p->speed.x,6);
p->speed.y = truncateDecimal<float>(p->speed.y,6);
p->speed.z = truncateDecimal<float>(p->speed.z,6);
@ -2220,6 +2243,7 @@ void SplashParticleSystem::initParticle(Particle *p, int particleIndex){
p->energy= maxParticleEnergy;
p->size= particleSize;
p->color= color;
p->speedUpRelative= speedUpRelative;
p->speed= Vec3f(horizontalSpreadA * random.randRange(-1.0f, 1.0f) + horizontalSpreadB, verticalSpreadA
* random.randRange(-1.0f, 1.0f) + verticalSpreadB, horizontalSpreadA * random.randRange(-1.0f, 1.0f)
@ -2243,6 +2267,7 @@ void SplashParticleSystem::initParticle(Particle *p, int particleIndex){
p->accel.y = truncateDecimal<float>(p->accel.y,6);
p->accel.z = truncateDecimal<float>(p->accel.z,6);
p->speedUpConstant= Vec3f(speedUpConstant)*p->speed;
}
void SplashParticleSystem::updateParticle(Particle *p){
@ -2254,6 +2279,8 @@ void SplashParticleSystem::updateParticle(Particle *p){
p->pos.y = truncateDecimal<float>(p->pos.y,6);
p->pos.z = truncateDecimal<float>(p->pos.z,6);
p->speed += p->speedUpConstant;
p->speed=p->speed*(1+p->speedUpRelative);
p->speed= p->speed + p->accel;
p->speed.x = truncateDecimal<float>(p->speed.x,6);
p->speed.y = truncateDecimal<float>(p->speed.y,6);

View File

@ -561,7 +561,7 @@ void trimPathWithStartingSlash(string &path) {
}
}
void updatePathClimbingParts(string &path) {
void updatePathClimbingParts(string &path,bool processPreviousDirTokenCheck) {
// Update paths with /./
string::size_type pos = path.find("/./");
if(pos != string::npos && pos != 0) {
@ -569,9 +569,11 @@ void updatePathClimbingParts(string &path) {
path.erase(pos,2);
//pos--;
//printf("#1 CHANGE relative path from [%s] to [%s]\n",orig.c_str(),path.c_str());
pos = path.find("/./");
if(pos != string::npos && pos != 0) {
updatePathClimbingParts(path);
updatePathClimbingParts(path, processPreviousDirTokenCheck);
}
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("CHANGED relative path from [%s] to [%s]\n",orig.c_str(),path.c_str());
@ -581,39 +583,65 @@ void updatePathClimbingParts(string &path) {
string orig = path;
path.erase(pos,2);
//pos--;
//printf("#w CHANGE relative path from [%s] to [%s]\n",orig.c_str(),path.c_str());
pos = path.find("\\.\\");
if(pos != string::npos && pos != 0) {
updatePathClimbingParts(path);
updatePathClimbingParts(path, processPreviousDirTokenCheck);
}
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("CHANGED relative path from [%s] to [%s]\n",orig.c_str(),path.c_str());
}
// Update paths with ..
pos = path.find("..");
if(pos != string::npos && pos != 0) {
string orig = path;
path.erase(pos,2);
pos--;
if(path[pos] == '/' || path[pos] == '\\') {
path.erase(pos,1);
}
for(int x = (int)pos; x >= 0; --x) {
//printf("x [%d][%c] pos [%ld][%c] [%s]\n",x,path[x],(long int)pos,path[pos],path.substr(0,x+1).c_str());
if((path[x] == '/' || path[x] == '\\') && x != (int)pos) {
path.erase(x,pos-x);
break;
}
}
if(processPreviousDirTokenCheck) {
pos = path.find("..");
if(pos != string::npos && pos != 0) {
updatePathClimbingParts(path);
}
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("CHANGED relative path from [%s] to [%s]\n",orig.c_str(),path.c_str());
string orig = path;
if(path[pos-1] != ' ' || (path.length() > 2 && path[pos+2] != ' ')) {
path.erase(pos,2);
//printf("#3 [%d] CHANGE relative path from [%s] to [%s]\n",(int)pos,orig.c_str(),path.c_str());
pos--;
//pos = pos -1;
//printf("^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ #3b [%d]\n",(int)pos);
if(path[pos] == '/' || path[pos] == '\\') {
path.erase(pos,1);
//printf("#4 CHANGE relative path from [%s] to [%s]\n",orig.c_str(),path.c_str());
}
for(int x = (int)pos; x >= 0; --x) {
//printf("x [%d][%c] pos [%ld][%c] [%s]\n",x,path[x],(long int)pos,path[pos],path.substr(0,x+1).c_str());
if((path[x] == '/' || path[x] == '\\') && x != (int)pos) {
string origLoop = path;
path.erase(x,(int)pos-x);
//printf("#5 [%d] [%d] [%d] CHANGE relative path from [%s] to [%s]\n",(int)pos,(int)x,(int)origLoop.length(),origLoop.c_str(),path.c_str());
break;
}
}
pos = path.find("..");
}
else {
//printf("#6a [%d]\n",(int)pos);
//pos = path.find("..",pos+1);
pos = string::npos;
//printf("#6b [%d]\n",(int)pos);
}
if(pos != string::npos && pos != 0) {
updatePathClimbingParts(path,processPreviousDirTokenCheck);
}
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("CHANGED relative path from [%s] to [%s]\n",orig.c_str(),path.c_str());
}
}
/*

View File

@ -317,47 +317,47 @@ void event_channel(irc_session_t * session, const char * event, const char * ori
}
}
if ( !strcmp (params[1], "quit") )
irc_cmd_quit (session, "of course, Master!");
if ( !strcmp (params[1], "help") ) {
irc_cmd_msg (session, params[0], "quit, help, dcc chat, dcc send, ctcp");
}
if ( !strcmp (params[1], "ctcp") ) {
irc_cmd_ctcp_request (session, realNick, "PING 223");
irc_cmd_ctcp_request (session, realNick, "FINGER");
irc_cmd_ctcp_request (session, realNick, "VERSION");
irc_cmd_ctcp_request (session, realNick, "TIME");
}
if ( !strcmp (params[1], "dcc chat") ) {
irc_dcc_t dccid;
irc_dcc_chat (session, 0, realNick, dcc_recv_callback, &dccid);
if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("DCC chat ID: %d\n", dccid);
}
if ( !strcmp (params[1], "dcc send") ) {
irc_dcc_t dccid;
irc_dcc_sendfile (session, 0, realNick, "irctest.c", dcc_file_recv_callback, &dccid);
if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("DCC send ID: %d\n", dccid);
}
if ( !strcmp (params[1], "topic") ) {
irc_cmd_topic (session, params[0], 0);
}
else if ( strstr (params[1], "topic ") == params[1] ) {
irc_cmd_topic (session, params[0], params[1] + 6);
}
if ( strstr (params[1], "mode ") == params[1] )
irc_cmd_channel_mode (session, params[0], params[1] + 5);
if ( strstr (params[1], "nick ") == params[1] )
irc_cmd_nick (session, params[1] + 5);
if ( strstr (params[1], "whois ") == params[1] )
irc_cmd_whois (session, params[1] + 5);
// if ( !strcmp (params[1], "quit") )
// irc_cmd_quit (session, "of course, Master!");
//
// if ( !strcmp (params[1], "help") ) {
// irc_cmd_msg (session, params[0], "quit, help, dcc chat, dcc send, ctcp");
// }
//
// if ( !strcmp (params[1], "ctcp") ) {
// irc_cmd_ctcp_request (session, realNick, "PING 223");
// irc_cmd_ctcp_request (session, realNick, "FINGER");
// irc_cmd_ctcp_request (session, realNick, "VERSION");
// irc_cmd_ctcp_request (session, realNick, "TIME");
// }
//
// if ( !strcmp (params[1], "dcc chat") ) {
// irc_dcc_t dccid;
// irc_dcc_chat (session, 0, realNick, dcc_recv_callback, &dccid);
// if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("DCC chat ID: %d\n", dccid);
// }
//
// if ( !strcmp (params[1], "dcc send") ) {
// irc_dcc_t dccid;
// irc_dcc_sendfile (session, 0, realNick, "irctest.c", dcc_file_recv_callback, &dccid);
// if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("DCC send ID: %d\n", dccid);
// }
//
// if ( !strcmp (params[1], "topic") ) {
// irc_cmd_topic (session, params[0], 0);
// }
// else if ( strstr (params[1], "topic ") == params[1] ) {
// irc_cmd_topic (session, params[0], params[1] + 6);
// }
//
// if ( strstr (params[1], "mode ") == params[1] )
// irc_cmd_channel_mode (session, params[0], params[1] + 5);
//
// if ( strstr (params[1], "nick ") == params[1] )
// irc_cmd_nick (session, params[1] + 5);
//
// if ( strstr (params[1], "whois ") == params[1] )
// irc_cmd_whois (session, params[1] + 5);
}
void irc_event_dcc_chat(irc_session_t * session, const char * nick, const char * addr, irc_dcc_t dccid) {

View File

@ -285,13 +285,15 @@ bool Properties::isValuePathVariable(const string &value) {
}
return false;
}
void Properties::updateValuePathVariable(string &value) {
void Properties::updateValuePathVariable(string &value, bool skipUpdatePathClimbingParts) {
replaceAll(value,"//","/");
replaceAll(value,"\\\\","\\");
updatePathClimbingParts(value);
if(skipUpdatePathClimbingParts == false) {
updatePathClimbingParts(value);
}
}
bool Properties::applyTagsToValue(string &value, const std::map<string,string> *mapTagReplacementValues) {
bool Properties::applyTagsToValue(string &value, const std::map<string,string> *mapTagReplacementValues,bool skipUpdatePathClimbingParts) {
string originalValue = value;
bool valueRequiresPathUpdate = Properties::isValuePathVariable(value);
//if(originalValue.find("$APPLICATIONDATAPATH") != string::npos) {
@ -389,7 +391,7 @@ bool Properties::applyTagsToValue(string &value, const std::map<string,string> *
//}
if(valueRequiresPathUpdate == true) {
Properties::updateValuePathVariable(value);
Properties::updateValuePathVariable(value, skipUpdatePathClimbingParts);
}
return (originalValue != value);
}

View File

@ -339,7 +339,8 @@ XmlIoRapid::~XmlIoRapid() {
cleanup();
}
XmlNode *XmlIoRapid::load(const string &path, const std::map<string,string> &mapTagReplacementValues,bool noValidation,bool skipStackTrace) {
XmlNode *XmlIoRapid::load(const string &path, const std::map<string,string> &mapTagReplacementValues,
bool noValidation,bool skipStackTrace,bool skipUpdatePathClimbingParts) {
bool showPerfStats = SystemFlags::VERBOSE_MODE_ENABLED;
Chrono chrono;
chrono.start();
@ -388,7 +389,7 @@ XmlNode *XmlIoRapid::load(const string &path, const std::map<string,string> &map
// Load data and add terminating 0
vector<char> buffer;
buffer.resize((unsigned int)file_size + 1);
buffer.resize((unsigned int)file_size + 100);
xmlFile.read(&buffer.front(), static_cast<streamsize>(file_size));
buffer[(unsigned int)file_size] = 0;
@ -405,7 +406,7 @@ XmlNode *XmlIoRapid::load(const string &path, const std::map<string,string> &map
if(showPerfStats) printf("In [%s::%s Line: %d] took msecs: " MG_I64_SPECIFIER "\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,chrono.getMillis());
rootNode= new XmlNode(doc.first_node(),mapTagReplacementValues);
rootNode= new XmlNode(doc.first_node(),mapTagReplacementValues, skipUpdatePathClimbingParts);
if(showPerfStats) printf("In [%s::%s Line: %d] took msecs: " MG_I64_SPECIFIER "\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,chrono.getMillis());
@ -522,6 +523,7 @@ XmlTree::XmlTree(xml_engine_parser_type engine_type) {
this->engine_type = engine_type;
this->skipStackCheck = false;
this->skipUpdatePathClimbingParts = false;
}
void XmlTree::init(const string &name){
@ -533,6 +535,10 @@ typedef std::vector<XmlTree*> LoadStack;
//static LoadStack loadStack;
static string loadStackCacheName = string(__FILE__) + string("_loadStackCacheName");
void XmlTree::setSkipUpdatePathClimbingParts(bool value) {
this->skipUpdatePathClimbingParts = value;
}
void XmlTree::load(const string &path, const std::map<string,string> &mapTagReplacementValues, bool noValidation,bool skipStackCheck,bool skipStackTrace) {
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d] about to load [%s] skipStackCheck = %d\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,path.c_str(),skipStackCheck);
@ -565,7 +571,7 @@ void XmlTree::load(const string &path, const std::map<string,string> &mapTagRepl
else
#endif
{
this->rootNode= XmlIoRapid::getInstance().load(path, mapTagReplacementValues, noValidation,skipStackTrace);
this->rootNode= XmlIoRapid::getInstance().load(path, mapTagReplacementValues, noValidation,skipStackTrace, this->skipUpdatePathClimbingParts);
}
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d] about to load [%s]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,path.c_str());
@ -661,7 +667,8 @@ XmlNode::XmlNode(DOMNode *node, const std::map<string,string> &mapTagReplacement
#endif
XmlNode::XmlNode(xml_node<> *node, const std::map<string,string> &mapTagReplacementValues) : superNode(NULL) {
XmlNode::XmlNode(xml_node<> *node, const std::map<string,string> &mapTagReplacementValues,
bool skipUpdatePathClimbingParts) : superNode(NULL) {
if(node == NULL || node->name() == NULL) {
throw megaglest_runtime_error("XML structure seems to be corrupt!");
}
@ -682,7 +689,7 @@ XmlNode::XmlNode(xml_node<> *node, const std::map<string,string> &mapTagReplacem
for(xml_node<> *currentNode = node->first_node();
currentNode; currentNode = currentNode->next_sibling()) {
if(currentNode != NULL && currentNode->type() == node_element) {
XmlNode *xmlNode= new XmlNode(currentNode, mapTagReplacementValues);
XmlNode *xmlNode= new XmlNode(currentNode, mapTagReplacementValues, skipUpdatePathClimbingParts);
children.push_back(xmlNode);
}
}
@ -696,8 +703,18 @@ XmlNode::XmlNode(xml_node<> *node, const std::map<string,string> &mapTagReplacem
//get value
if(node->type() == node_element && children.size() == 0) {
text = node->value();
Properties::applyTagsToValue(this->text,&mapTagReplacementValues);
string xmlText = node->value();
bool debugReplace = false;
// if(xmlText.find("{SCENARIOPATH}") != string::npos) {
// printf("\n----------------------\n** XML!! WILL REPLACE [%s]\n",xmlText.c_str());
// debugReplace = true;
// }
Properties::applyTagsToValue(xmlText,&mapTagReplacementValues, skipUpdatePathClimbingParts);
if(debugReplace) {
printf("\n\n** XML!! REPLACED WITH [%s]\n===================\n",xmlText.c_str());
}
text = xmlText;
}
}