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) 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)") 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() 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()
ENDIF() ENDIF()
SET(CUSTOM_DATA_INSTALL_PATH_VALUE "-DCUSTOM_DATA_INSTALL_PATH=${CUSTOM_DATA_INSTALL_PATH}") 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_DATADIR ${CUSTOM_DATA_INSTALL_PATH_VALUE})
SET(PKG_BINDIR ${MEGAGLEST_BIN_INSTALL_PATH}) SET(PKG_BINDIR ${MEGAGLEST_BIN_INSTALL_PATH})

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

View File

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

View File

@ -148,7 +148,7 @@ case $distribution in
$installcommand $installcommand
if [ $? != 0 ]; then error_during_installation; exit 1; fi 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='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 $installcommand
if [ $? != 0 ]; then error_during_installation; exit 1; fi if [ $? != 0 ]; then error_during_installation; exit 1; fi
@ -167,7 +167,7 @@ case $distribution in
fi fi
case $release in 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='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 $installcommand
if [ $? != 0 ]; then error_during_installation; exit 1; fi if [ $? != 0 ]; then error_during_installation; exit 1; fi
@ -180,7 +180,7 @@ case $distribution in
esac esac
;; ;;
SuSE|SUSE?LINUX|Opensuse) SuSE|SUSE?LINUX|Opensuse*|openSUSE*)
case $release in case $release in
11.2|11.3|11.4|12.1) 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' 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 $installcommand
if [ $? != 0 ]; then error_during_installation; exit 1; fi 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' 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 unsupported_release

View File

@ -269,6 +269,7 @@
<ClCompile Include="..\..\source\glest_game\types\object_type.cpp" /> <ClCompile Include="..\..\source\glest_game\types\object_type.cpp" />
<ClCompile Include="..\..\source\glest_game\types\resource_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\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\tech_tree.cpp" />
<ClCompile Include="..\..\source\glest_game\types\unit_type.cpp" /> <ClCompile Include="..\..\source\glest_game\types\unit_type.cpp" />
<ClCompile Include="..\..\source\glest_game\types\upgrade_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\object_type.h" />
<ClInclude Include="..\..\source\glest_game\types\resource_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\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\tech_tree.h" />
<ClInclude Include="..\..\source\glest_game\types\unit_type.h" /> <ClInclude Include="..\..\source\glest_game\types\unit_type.h" />
<ClInclude Include="..\..\source\glest_game\types\upgrade_type.h" /> <ClInclude Include="..\..\source\glest_game\types\upgrade_type.h" />

2
source/.gitignore vendored
View File

@ -1 +1,3 @@
/windows_deps*/ /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; *unitIndex= -1;
for(int i=0; i<aiInterface->getMyUnitCount(); ++i){ for(int i=0; i<aiInterface->getMyUnitCount(); ++i){
const Unit *unit= aiInterface->getMyUnit(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){ if(!idleOnly || !unit->anyCommand() || unit->getCurrCommand()->getCommandType()->getClass()==ccStop){
units.push_back(i); units.push_back(i);
} }
@ -553,55 +553,57 @@ vector<int> Ai::findUnitsHarvestingResourceType(const ResourceType *rt) {
Map *map= aiInterface->getMap(); Map *map= aiInterface->getMap();
for(int i = 0; i < aiInterface->getMyUnitCount(); ++i) { for(int i = 0; i < aiInterface->getMyUnitCount(); ++i) {
const Unit *unit= aiInterface->getMyUnit(i); const Unit *unit= aiInterface->getMyUnit(i);
if(unit->getType()->hasCommandClass(ccHarvest)) { if(unit->getType()->isCommandable()) {
if(unit->anyCommand() && unit->getCurrCommand()->getCommandType()->getClass() == ccHarvest) { if(unit->getType()->hasCommandClass(ccHarvest)) {
Command *command= unit->getCurrCommand(); if(unit->anyCommand() && unit->getCurrCommand()->getCommandType()->getClass() == ccHarvest) {
const HarvestCommandType *hct= dynamic_cast<const HarvestCommandType*>(command->getCommandType()); Command *command= unit->getCurrCommand();
if(hct != NULL) { const HarvestCommandType *hct= dynamic_cast<const HarvestCommandType*>(command->getCommandType());
const Vec2i unitTargetPos = unit->getTargetPos(); if(hct != NULL) {
SurfaceCell *sc= map->getSurfaceCell(Map::toSurfCoords(unitTargetPos)); const Vec2i unitTargetPos = unit->getTargetPos();
Resource *r= sc->getResource(); SurfaceCell *sc= map->getSurfaceCell(Map::toSurfCoords(unitTargetPos));
if (r != NULL && r->getType() == rt) { Resource *r= sc->getResource();
units.push_back(i); 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);
}
} }
} }
} }
} }
} else if(unit->getType()->hasCommandClass(ccProduce)) {
else if(unit->getType()->hasCommandClass(ccBuild)) { if(unit->anyCommand() && unit->getCurrCommand()->getCommandType()->getClass() == ccProduce) {
if(unit->anyCommand() && unit->getCurrCommand()->getCommandType()->getClass() == ccBuild) { Command *command= unit->getCurrCommand();
Command *command= unit->getCurrCommand(); const ProduceCommandType *pct= dynamic_cast<const ProduceCommandType*>(command->getCommandType());
const BuildCommandType *bct= dynamic_cast<const BuildCommandType*>(command->getCommandType()); if(pct != NULL) {
if(bct != NULL) { const UnitType *ut = pct->getProducedUnit();
for(int j = 0; j < bct->getBuildingCount(); ++j) {
const UnitType *ut = bct->getBuilding(j);
if(ut != NULL) { if(ut != NULL) {
const Resource *r = ut->getCost(rt); const Resource *r = ut->getCost(rt);
if(r != NULL) { if(r != NULL) {
if (r != NULL && r->getAmount() < 0) { if (r != NULL && r->getAmount() < 0) {
units.push_back(i); 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) { for(int i = 0; i < aiInterface->getMyUnitCount(); ++i) {
const Unit *unit= aiInterface->getMyUnit(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) { if(unit->anyCommand() && unit->getCurrCommand()->getCommandType()->getClass() == currentCommand) {
units.push_back(i); units.push_back(i);
} }
@ -630,7 +632,7 @@ bool Ai::findAbleUnit(int *unitIndex, CommandClass ability, CommandClass current
*unitIndex= -1; *unitIndex= -1;
for(int i=0; i<aiInterface->getMyUnitCount(); ++i){ for(int i=0; i<aiInterface->getMyUnitCount(); ++i){
const Unit *unit= aiInterface->getMyUnit(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){ if(unit->anyCommand() && unit->getCurrCommand()->getCommandType()->getClass()==currentCommand){
units.push_back(i); 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)); Config &configKeys = Config::getInstance(std::pair<ConfigType,ConfigType>(cfgMainKeys,cfgUserKeys));
//toggle team mode //toggle team mode
if(editEnabled == false && disableTeamMode == false && if(editEnabled == false &&
isKeyPressed(configKeys.getSDLKey("ChatTeamMode"),key) == true) { 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 (!inMenu) {
if (teamMode == true) { if (teamMode == true) {
teamMode = false; teamMode = false;
console->addLine(lang.getString("ChatMode") + ": " + lang.getString("All")); console->addLine(lang.getString("ChatMode") + ": " + lang.getString("All"));
} else { } else {
teamMode = true; teamMode = true;
console->addLine(lang.getString("ChatMode") + ": " + lang.getString("Team")); console->addLine(lang.getString("ChatMode") + ": " + lang.getString("Team"));
}
} }
} }
} }
if(isKeyPressed(SDLK_RETURN,key, false) == true) { 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); 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) { for(int i = 0; i < world.getFactionCount(); ++i) {
string factionInfo = this->gameSettings.getNetworkPlayerName(i); string factionInfo = this->gameSettings.getNetworkPlayerName(i);
//factionInfo += " [" + this->gameSettings.getNetworkPlayerUUID(i) + "]"; //factionInfo += " [" + this->gameSettings.getNetworkPlayerUUID(i) + "]";
float multi=world.getStats()->getResourceMultiplier(i);
string multiplier="["+floatToStr(multi,1)+"]";
switch(this->gameSettings.getFactionControl(i)) { switch(this->gameSettings.getFactionControl(i)) {
case ctCpuEasy: case ctCpuEasy:
factionInfo += " CPU Easy"; factionInfo += " CPU Easy"+multiplier;
break; break;
case ctCpu: case ctCpu:
factionInfo += " CPU Normal"; factionInfo += " CPU Normal"+multiplier;
break; break;
case ctCpuUltra: case ctCpuUltra:
factionInfo += " CPU Ultra"; factionInfo += " CPU Ultra"+multiplier;
break; break;
case ctCpuMega: case ctCpuMega:
factionInfo += " CPU Mega"; factionInfo += " CPU Mega"+multiplier;
break; break;
} }

View File

@ -1531,6 +1531,12 @@ int ScriptManager::getUnitFaction(int unitId) {
const string ScriptManager::getUnitName(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__); 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); return world->getUnitName(unitId);
} }
@ -3414,6 +3420,7 @@ int ScriptManager::getUnitFaction(LuaHandle* luaHandle){
return luaArguments.getReturnCount(); return luaArguments.getReturnCount();
} }
int ScriptManager::getUnitName(LuaHandle* luaHandle){ int ScriptManager::getUnitName(LuaHandle* luaHandle){
LuaArguments luaArguments(luaHandle); LuaArguments luaArguments(luaHandle);
try { try {
@ -3435,6 +3442,28 @@ int ScriptManager::getUnitName(LuaHandle* luaHandle){
return luaArguments.getReturnCount(); 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){ int ScriptManager::getResourceAmount(LuaHandle* luaHandle){
LuaArguments luaArguments(luaHandle); LuaArguments luaArguments(luaHandle);
try { try {

View File

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

View File

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

View File

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

View File

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

View File

@ -71,6 +71,11 @@ bool Selection::select(Unit *unit) {
return false; return false;
} }
//check if commandable
if(unit->getType()->isCommandable() == false && isEmpty() == false) {
return false;
}
//check if multisel //check if multisel
if(unit->getType()->getMultiSelect() == false && isEmpty() == false) { if(unit->getType()->getMultiSelect() == false && isEmpty() == false) {
return false; return false;
@ -181,7 +186,8 @@ bool Selection::isCommandable() const {
return return
isEmpty() == false && isEmpty() == false &&
isEnemy() == 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 { bool Selection::isCancelable() const {

View File

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

View File

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

View File

@ -666,27 +666,7 @@ Unit::~Unit() {
} }
safeMutex.ReleaseLock(); safeMutex.ReleaseLock();
// If the unit is not visible we better make sure we cleanup associated particles cleanupAllParticlesystems();
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);
while(currentAttackBoostEffects.empty() == false) { while(currentAttackBoostEffects.empty() == false) {
//UnitAttackBoostEffect &effect = currentAttackBoostEffects.back(); //UnitAttackBoostEffect &effect = currentAttackBoostEffects.back();
@ -726,6 +706,29 @@ Unit::~Unit() {
#endif #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 { ParticleSystem * Unit::getFire() const {
if(this->fire != NULL && if(this->fire != NULL &&
Renderer::getInstance().validateParticleSystemStillExists(this->fire,rsGame) == false) { Renderer::getInstance().validateParticleSystemStillExists(this->fire,rsGame) == false) {
@ -1951,13 +1954,32 @@ void Unit::born(const CommandType *ct) {
checkItemInVault(&this->hp,this->hp); checkItemInVault(&this->hp,this->hp);
int original_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) { if(original_hp != this->hp) {
//printf("File: %s line: %d\n",extractFileFromDirectoryPath(__FILE__).c_str(),__LINE__); //printf("File: %s line: %d\n",extractFileFromDirectoryPath(__FILE__).c_str(),__LINE__);
game->getScriptManager()->onUnitTriggerEvent(this,utet_HPChanged); game->getScriptManager()->onUnitTriggerEvent(this,utet_HPChanged);
//printf("File: %s line: %d\n",extractFileFromDirectoryPath(__FILE__).c_str(),__LINE__); //printf("File: %s line: %d\n",extractFileFromDirectoryPath(__FILE__).c_str(),__LINE__);
} }
addItemToVault(&this->hp,this->hp); 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() { void Unit::kill() {
@ -2611,7 +2633,15 @@ bool Unit::update() {
int64 heightFactor = getHeightFactor(ANIMATION_SPEED_MULTIPLIER); int64 heightFactor = getHeightFactor(ANIMATION_SPEED_MULTIPLIER);
int64 speedDenominator = speedDivider * int64 speedDenominator = speedDivider *
game->getWorld()->getUpdateFps(this->getFactionIndex()); 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 // Ensure we increment at least a value of 1 of the action will be stuck infinitely
if(currSkill->getAnimSpeed() > 0 && heightFactor > 0 && progressIncrease == 0) { if(currSkill->getAnimSpeed() > 0 && heightFactor > 0 && progressIncrease == 0) {
progressIncrease = 1; progressIncrease = 1;
@ -2933,7 +2963,7 @@ bool Unit::applyAttackBoost(const AttackBoost *boost, const Unit *source) {
Unit::game->getWorld()->getStats()->die(getFactionIndex(),getType()->getCountUnitDeathInStats()); Unit::game->getWorld()->getStats()->die(getFactionIndex(),getType()->getCountUnitDeathInStats());
game->getScriptManager()->onUnitDied(this); 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 && if(sound != NULL &&
(this->getFactionIndex() == Unit::game->getWorld()->getThisFactionIndex() || (this->getFactionIndex() == Unit::game->getWorld()->getThisFactionIndex() ||
(game->getWorld()->showWorldForPlayer(game->getWorld()->getThisTeamIndex()) == true))) { (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()); Unit::game->getWorld()->getStats()->die(getFactionIndex(),getType()->getCountUnitDeathInStats());
game->getScriptManager()->onUnitDied(this); 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 && if(sound != NULL &&
(this->getFactionIndex() == Unit::game->getWorld()->getThisFactionIndex() || (this->getFactionIndex() == Unit::game->getWorld()->getThisFactionIndex() ||
(game->getWorld()->showWorldForPlayer(game->getWorld()->getThisTeamIndex()) == true))) { (game->getWorld()->showWorldForPlayer(game->getWorld()->getThisTeamIndex()) == true))) {
@ -3103,7 +3133,7 @@ void Unit::tick() {
Unit::game->getWorld()->getStats()->die(getFactionIndex(),getType()->getCountUnitDeathInStats()); Unit::game->getWorld()->getStats()->die(getFactionIndex(),getType()->getCountUnitDeathInStats());
game->getScriptManager()->onUnitDied(this); 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 && if(sound != NULL &&
(this->getFactionIndex() == Unit::game->getWorld()->getThisFactionIndex() || (this->getFactionIndex() == Unit::game->getWorld()->getThisFactionIndex() ||
(game->getWorld()->showWorldForPlayer(game->getWorld()->getThisTeamIndex()) == true))) { (game->getWorld()->showWorldForPlayer(game->getWorld()->getThisTeamIndex()) == true))) {
@ -3142,7 +3172,7 @@ void Unit::tick() {
Unit::game->getWorld()->getStats()->die(getFactionIndex(),getType()->getCountUnitDeathInStats()); Unit::game->getWorld()->getStats()->die(getFactionIndex(),getType()->getCountUnitDeathInStats());
game->getScriptManager()->onUnitDied(this); 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 && if(sound != NULL &&
(this->getFactionIndex() == Unit::game->getWorld()->getThisFactionIndex() || (this->getFactionIndex() == Unit::game->getWorld()->getThisFactionIndex() ||
(game->getWorld()->showWorldForPlayer(game->getWorld()->getThisTeamIndex()) == true))) { (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); checkItemInVault(&this->hp,this->hp);
int original_hp = this->hp; int original_hp = this->hp;

View File

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

View File

@ -9,6 +9,13 @@
// License, or (at your option) any later version // 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_ #ifndef _GLEST_GAME_UPGRADE_H_
#define _GLEST_GAME_UPGRADE_H_ #define _GLEST_GAME_UPGRADE_H_
@ -33,25 +40,32 @@ class Unit;
class UpgradeType; class UpgradeType;
class Faction; 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 { enum UpgradeState {
usUpgrading, usUpgrading, /**< The upgrade is currently in progress. */
usUpgraded, usUpgraded, /**< The upgrade is completed. */
upgradeStateCount upgradeStateCount // TODO: This should be unnecessary -- there's no need to iterate over this enum
}; };
class UpgradeManager; class UpgradeManager;
class TotalUpgrade; class TotalUpgrade;
// ===================================================== /**
// class Upgrade * 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?).
/// A bonus to an UnitType */
// =====================================================
class Upgrade { class Upgrade {
private: private:
UpgradeState state; 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; int factionIndex;
const UpgradeType *type; const UpgradeType *type;
@ -59,50 +73,136 @@ private:
Upgrade(); Upgrade();
public: 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); Upgrade(const UpgradeType *upgradeType, int factionIndex);
private: private:
//get
UpgradeState getState() const; UpgradeState getState() const;
int getFactionIndex() const; int getFactionIndex() const;
const UpgradeType * getType() const; const UpgradeType * getType() const;
//set
void setState(UpgradeState state); void setState(UpgradeState state);
/**
* Retrieves a string representation of the upgrade (detailing its state, type, and faction).
*/
std::string toString() const; 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); 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); static Upgrade * loadGame(const XmlNode *rootNode,Faction *faction);
}; };
/**
// =============================== * Manages upgrades by starting, stopping, and finishing upgrades. Each faction has their own
// class UpgradeManager * upgrade manager.
// =============================== */
class UpgradeManager{ class UpgradeManager{
private: private:
typedef vector<Upgrade*> Upgrades; typedef vector<Upgrade*> Upgrades;
typedef map<const UpgradeType *,int> UgradesLookup; typedef map<const UpgradeType *,int> UgradesLookup;
/**
* List of upgrades that the upgrade manager is working with (either in progress or finished).
*/
Upgrades upgrades; Upgrades upgrades;
/**
* Maps UpgradeType to the index of the upgrade in UpgradeManager::upgrades.
*/
UgradesLookup upgradesLookup; UgradesLookup upgradesLookup;
public: public:
~UpgradeManager(); ~UpgradeManager();
int getUpgradeCount() const {return (int)upgrades.size();} 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); 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); 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); 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 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; 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); 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); void loadGame(const XmlNode *rootNode,Faction *faction);
}; };

View File

@ -288,7 +288,13 @@ string AttackCommandType::getDesc(const TotalUpgrade *totalUpgrade, bool transla
} }
str+="\n"; str+="\n";
//attack speed
str+= lang.getString("AttackSpeed",(translatedValue == true ? "" : "english"))+": "+ intToStr(attackSkillType->getSpeed()) +"\n"; 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); str+=attackSkillType->getBoostDesc(translatedValue);
return str; 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 "renderer.h"
#include "particle_type.h" #include "particle_type.h"
#include "unit_particle_type.h" #include "unit_particle_type.h"
#include "projectile_type.h"
#include "tech_tree.h" #include "tech_tree.h"
#include "faction_type.h" #include "faction_type.h"
#include "leak_dumper.h" #include "leak_dumper.h"
@ -273,12 +274,27 @@ void AttackBoost::saveGame(XmlNode *rootNode) const {
attackBoostNode->addAttribute("name",name, mapTagReplacements); 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 // class SkillType
// ===================================================== // =====================================================
SkillType::~SkillType() { SkillType::~SkillType() {
deleteValues(sounds.getSounds().begin(), sounds.getSounds().end()); while(!skillSoundList.empty()) {
delete skillSoundList.back();
skillSoundList.pop_back();
}
//remove unitParticleSystemTypes //remove unitParticleSystemTypes
while(!unitParticleSystemTypes.empty()) { while(!unitParticleSystemTypes.empty()) {
delete unitParticleSystemTypes.back(); delete unitParticleSystemTypes.back();
@ -488,11 +504,18 @@ void SkillType::load(const XmlNode *sn, const XmlNode *attackBoostsNode,
unitParticleSystemType->load(particleFileNode, dir, currentPath + path, &Renderer::getInstance(), unitParticleSystemType->load(particleFileNode, dir, currentPath + path, &Renderer::getInstance(),
loadedFileList,parentLoader,tt->getPath()); 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()); //printf("*NOTE particle system type has start-time [%f]\n",particleNode->getAttribute("start-time")->getFloatValue());
unitParticleSystemType->setStartTime(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()); //printf("*NOTE particle system type has end-time [%f]\n",particleNode->getAttribute("end-time")->getFloatValue());
unitParticleSystemType->setEndTime(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 //sound
if(sn->hasChild("sound")) { vector<XmlNode *> soundNodeList = sn->getChildList("sound");
const XmlNode *soundNode= sn->getChild("sound"); for(unsigned int i = 0; i < soundNodeList.size(); ++i) {
const XmlNode *soundNode= soundNodeList[i];
if(soundNode->getAttribute("enabled")->getBoolValue()) { if(soundNode->getAttribute("enabled")->getBoolValue()) {
soundStartTime= soundNode->getAttribute("start-time")->getFloatValue(); float soundStartTime= soundNode->getAttribute("start-time")->getFloatValue();
sounds.resize((int)soundNode->getChildCount()); 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) { for(int i = 0; i < (int)soundNode->getChildCount(); ++i) {
const XmlNode *soundFileNode= soundNode->getChild("sound-file", i); const XmlNode *soundFileNode= soundNode->getChild("sound-file", i);
string path= soundFileNode->getAttribute("path")->getRestrictedValue(currentPath, true); 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(); StaticSound *sound= new StaticSound();
sound->load(path); sound->load(path);
loadedFileList[path].push_back(make_pair(parentLoader,soundFileNode->getAttribute("path")->getRestrictedValue())); 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; // SoundContainer sounds;
// float soundStartTime; // float soundStartTime;
skillTypeNode->addAttribute("soundStartTime",floatToStr(soundStartTime,6), mapTagReplacements); // skillTypeNode->addAttribute("soundStartTime",floatToStr(soundStartTime,6), mapTagReplacements);
// RandomGen random; // RandomGen random;
skillTypeNode->addAttribute("random",intToStr(random.getLastNumber()), mapTagReplacements); skillTypeNode->addAttribute("random",intToStr(random.getLastNumber()), mapTagReplacements);
// AttackBoost attackBoost; // AttackBoost attackBoost;
@ -806,7 +834,7 @@ AttackSkillType::AttackSkillType() {
splashRadius= 0; splashRadius= 0;
spawnUnit=""; spawnUnit="";
spawnUnitcount=0; spawnUnitcount=0;
projectileParticleSystemType= NULL; spawnUnitAtTarget=false;
splashParticleSystemType= NULL; splashParticleSystemType= NULL;
for(int i = 0; i < fieldCount; ++i) { for(int i = 0; i < fieldCount; ++i) {
@ -821,8 +849,8 @@ AttackSkillType::AttackSkillType() {
} }
AttackSkillType::~AttackSkillType() { AttackSkillType::~AttackSkillType() {
delete projectileParticleSystemType;
projectileParticleSystemType = NULL; deleteValues(projectileTypes.begin(), projectileTypes.end());
delete splashParticleSystemType; delete splashParticleSystemType;
splashParticleSystemType = NULL; splashParticleSystemType = NULL;
@ -859,11 +887,16 @@ void AttackSkillType::load(const XmlNode *sn, const XmlNode *attackBoostsNode,
if (sn->hasChild("unit")) { if (sn->hasChild("unit")) {
spawnUnit = sn->getChild("unit")->getAttribute("value")->getValue(); spawnUnit = sn->getChild("unit")->getAttribute("value")->getValue();
spawnUnitcount spawnUnitcount = sn->getChild("unit")->getAttribute("amount")->getIntValue();
= sn->getChild("unit")->getAttribute("amount")->getIntValue(); if(sn->getChild("unit")->hasAttribute("spawnAtTarget")) {
spawnUnitAtTarget = sn->getChild("unit")->getAttribute("spawnAtTarget")->getBoolValue();
} else {
spawnUnitAtTarget = false;
}
} else { } else {
spawnUnit = ""; spawnUnit = "";
spawnUnitcount = 0; spawnUnitcount = 0;
spawnUnitAtTarget = false;
} }
//attack fields //attack fields
const XmlNode *attackFieldsNode= sn->getChild("attack-fields"); const XmlNode *attackFieldsNode= sn->getChild("attack-fields");
@ -881,36 +914,81 @@ void AttackSkillType::load(const XmlNode *sn, const XmlNode *attackBoostsNode,
} }
} }
//projectile if(sn->hasChild("projectile")){
const XmlNode *projectileNode= sn->getChild("projectile"); //projectile -- backward compatible old behaviour with only one projectile
projectile= projectileNode->getAttribute("value")->getBoolValue(); const XmlNode *projectileNode= sn->getChild("projectile");
if(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 projSounds.resize((int)soundNode->getChildCount());
const XmlNode *particleNode= projectileNode->getChild("particle"); for(int i=0; i < (int)soundNode->getChildCount(); ++i){
bool particleEnabled= particleNode->getAttribute("value")->getBoolValue(); const XmlNode *soundFileNode= soundNode->getChild("sound-file", i);
if(particleEnabled){ string path= soundFileNode->getAttribute("path")->getRestrictedValue(currentPath, true);
string path= particleNode->getAttribute("path")->getRestrictedValue(); //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);
projectileParticleSystemType= new ParticleSystemTypeProjectile();
projectileParticleSystemType->load(particleNode, dir, currentPath + path, StaticSound *sound= new StaticSound();
&Renderer::getInstance(), loadedFileList, parentLoader, sound->load(path);
tt->getPath()); 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 if(totalDamagePercentage!=100){
const XmlNode *soundNode= projectileNode->getChild("sound"); throw megaglest_runtime_error("Damages percentages of projectiles don't sum up to 100 %");
if(soundNode->getAttribute("enabled")->getBoolValue()){ }
projSounds.resize((int)soundNode->getChildCount()); if(sn->hasChild("hitsound")==true){
for(int i=0; i < (int)soundNode->getChildCount(); ++i){ //general hit sounds, individual ones can be set in projectiles
const XmlNode *soundFileNode= soundNode->getChild("sound-file", i); const XmlNode *soundNode= sn->getChild("hitsound");
string path= soundFileNode->getAttribute("path")->getRestrictedValue(currentPath, true); if(soundNode->getAttribute("enabled")->getBoolValue()){
//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(); projSounds.resize((int)soundNode->getChildCount());
sound->load(path); for(int i=0; i < (int)soundNode->getChildCount(); ++i){
loadedFileList[path].push_back(make_pair(parentLoader,soundFileNode->getAttribute("path")->getRestrictedValue())); const XmlNode *soundFileNode= soundNode->getChild("sound-file", i);
projSounds[i]= sound; 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{ string AttackSkillType::toString(bool translatedValue) const{
if(translatedValue == false) { if(translatedValue == false) {
return "Attack"; return "Attack";
@ -983,12 +1079,15 @@ void AttackSkillType::saveGame(XmlNode *rootNode) {
attackSkillTypeNode->addAttribute("spawnUnit",spawnUnit, mapTagReplacements); attackSkillTypeNode->addAttribute("spawnUnit",spawnUnit, mapTagReplacements);
// int spawnUnitcount; // int spawnUnitcount;
attackSkillTypeNode->addAttribute("spawnUnitcount",intToStr(spawnUnitcount), mapTagReplacements); attackSkillTypeNode->addAttribute("spawnUnitcount",intToStr(spawnUnitcount), mapTagReplacements);
// bool spawnUnitAtTarget;
attackSkillTypeNode->addAttribute("spawnUnitAtTarget",intToStr(spawnUnitAtTarget), mapTagReplacements);
// bool projectile; // bool projectile;
attackSkillTypeNode->addAttribute("projectile",intToStr(projectile), mapTagReplacements); attackSkillTypeNode->addAttribute("projectile",intToStr(projectile), mapTagReplacements);
// ParticleSystemTypeProjectile* projectileParticleSystemType; // ParticleSystemTypeProjectile* projectileParticleSystemType;
if(projectileParticleSystemType != NULL) { // save a skill_type ????
projectileParticleSystemType->saveGame(attackSkillTypeNode); // if(projectileParticleSystemType != NULL) {
} // projectileParticleSystemType->saveGame(attackSkillTypeNode);
// }
// SoundContainer projSounds; // SoundContainer projSounds;
// //
// bool splash; // bool splash;
@ -1262,6 +1361,15 @@ void DieSkillType::saveGame(XmlNode *rootNode) {
dieSkillTypeNode->addAttribute("fade",intToStr(fade), mapTagReplacements); dieSkillTypeNode->addAttribute("fade",intToStr(fade), mapTagReplacements);
} }
StaticSound *DieSkillType::getSound() const{
if(skillSoundList.size()==0){
return NULL;
}
else {
return skillSoundList.front()->getSoundContainer()->getRandSound();
}
}
// ===================================================== // =====================================================
// class FogOfWarSkillType // class FogOfWarSkillType

View File

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

View File

@ -89,6 +89,7 @@ UnitType::UnitType() : ProducibleType() {
lightColor= Vec3f(0.f); lightColor= Vec3f(0.f);
light= false; light= false;
multiSelect= false; multiSelect= false;
commandable= true;
armorType= NULL; armorType= NULL;
rotatedBuildPos=0; rotatedBuildPos=0;
@ -125,7 +126,13 @@ UnitType::UnitType() : ProducibleType() {
epRegeneration= 0; epRegeneration= 0;
maxUnitCount= 0; maxUnitCount= 0;
maxHp=0; maxHp=0;
startHpValue=0;
startHpPercentage=1.0;
startHpType=stValue;
maxEp=0; maxEp=0;
startEpValue=0;
startEpPercentage=0;
startEpType=stValue;
armor=0; armor=0;
sight=0; sight=0;
size=0; size=0;
@ -247,6 +254,59 @@ void UnitType::loaddd(int id,const string &dir, const TechTree *techTree,
} }
addItemToVault(&(this->epRegeneration),this->epRegeneration); 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 //maxUnitCount
if(parametersNode->hasChild("max-unit-count")) { if(parametersNode->hasChild("max-unit-count")) {
//checkItemInVault(&(this->maxUnitCount),this->maxUnitCount); //checkItemInVault(&(this->maxUnitCount),this->maxUnitCount);
@ -274,6 +334,10 @@ void UnitType::loaddd(int id,const string &dir, const TechTree *techTree,
//multi selection //multi selection
multiSelect= parametersNode->getChild("multi-selection")->getAttribute("value")->getBoolValue(); multiSelect= parametersNode->getChild("multi-selection")->getAttribute("value")->getBoolValue();
//commandable
if(parametersNode->hasChild("commandable")){
commandable= parametersNode->getChild("commandable")->getAttribute("value")->getBoolValue();
}
//cellmap //cellmap
allowEmptyCellMap = false; allowEmptyCellMap = false;
const XmlNode *cellMapNode= parametersNode->getChild("cellmap"); const XmlNode *cellMapNode= parametersNode->getChild("cellmap");
@ -532,6 +596,65 @@ void UnitType::loaddd(int id,const string &dir, const TechTree *techTree,
} }
} }
sortedItems.clear(); 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 //image
const XmlNode *imageNode= parametersNode->getChild("image"); const XmlNode *imageNode= parametersNode->getChild("image");
@ -1100,6 +1223,8 @@ std::string UnitType::toString() const {
result += " maxHp = " + intToStr(maxHp); result += " maxHp = " + intToStr(maxHp);
result += " hpRegeneration = " + intToStr(hpRegeneration); result += " hpRegeneration = " + intToStr(hpRegeneration);
result += " maxEp = " + intToStr(maxEp); result += " maxEp = " + intToStr(maxEp);
result += " startEpValue = " + intToStr(startEpValue);
result += " startEpPercentage = " + intToStr(startEpPercentage);
result += " epRegeneration = " + intToStr(epRegeneration); result += " epRegeneration = " + intToStr(epRegeneration);
result += " maxUnitCount = " + intToStr(getMaxUnitCount()); result += " maxUnitCount = " + intToStr(getMaxUnitCount());
@ -1120,6 +1245,7 @@ std::string UnitType::toString() const {
result += " light = " + intToStr(light); result += " light = " + intToStr(light);
result += " lightColor = " + lightColor.getString(); result += " lightColor = " + lightColor.getString();
result += " multiSelect = " + intToStr(multiSelect); result += " multiSelect = " + intToStr(multiSelect);
result += " commandable = " + intToStr(commandable);
result += " sight = " + intToStr(sight); result += " sight = " + intToStr(sight);
result += " size = " + intToStr(size); result += " size = " + intToStr(size);
result += " height = " + intToStr(height); result += " height = " + intToStr(height);

View File

@ -63,6 +63,45 @@ public:
static const Level * loadGame(const XmlNode *rootNode, const UnitType *ut); 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 // class UnitType
// //
@ -92,6 +131,11 @@ public:
pCount pCount
}; };
enum StartType {
stValue,
stPercentage
};
static const char *propertyNames[]; static const char *propertyNames[];
DamageParticleSystemTypes damageParticleSystemTypes; DamageParticleSystemTypes damageParticleSystemTypes;
private: private:
@ -99,13 +143,20 @@ private:
typedef vector<CommandType*> CommandTypes; typedef vector<CommandType*> CommandTypes;
typedef vector<Resource> StoredResources; typedef vector<Resource> StoredResources;
typedef vector<Level> Levels; typedef vector<Level> Levels;
typedef vector<LootableResource> LootableResources;
private: private:
//basic //basic
int id; int id;
int maxHp; int maxHp;
int startHpValue;
int startHpPercentage;
StartType startHpType;
int hpRegeneration; int hpRegeneration;
int maxEp; int maxEp;
int startEpValue;
int startEpPercentage;
StartType startEpType;
int epRegeneration; int epRegeneration;
int maxUnitCount; int maxUnitCount;
@ -120,6 +171,7 @@ private:
bool light; bool light;
Vec3f lightColor; Vec3f lightColor;
bool multiSelect; bool multiSelect;
bool commandable;
int sight; int sight;
int size; //size in cells int size; //size in cells
int renderSize; //size to render in cells int renderSize; //size to render in cells
@ -140,6 +192,7 @@ private:
CommandTypes commandTypes; CommandTypes commandTypes;
StoredResources storedResources; StoredResources storedResources;
Levels levels; Levels levels;
LootableResources lootableResources;
//meeting point //meeting point
bool meetingPoint; bool meetingPoint;
@ -178,8 +231,14 @@ public:
inline int getId() const {return id;} inline int getId() const {return id;}
inline int getMaxHp() const {return maxHp;} inline int getMaxHp() const {return maxHp;}
inline int getHpRegeneration() const {return hpRegeneration;} 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 getMaxEp() const {return maxEp;}
inline int getEpRegeneration() const {return epRegeneration;} 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 int getMaxUnitCount() const {return maxUnitCount;}
inline bool getField(Field field) const {return fields[field];} inline bool getField(Field field) const {return fields[field];}
inline Field getField() const {return field;} inline Field getField() const {return field;}
@ -197,12 +256,15 @@ public:
inline bool getRotationAllowed() const {return rotationAllowed;} inline bool getRotationAllowed() const {return rotationAllowed;}
inline Vec3f getLightColor() const {return lightColor;} inline Vec3f getLightColor() const {return lightColor;}
inline bool getMultiSelect() const {return multiSelect;} inline bool getMultiSelect() const {return multiSelect;}
inline bool isCommandable() const {return commandable;}
inline int getSight() const {return sight;} inline int getSight() const {return sight;}
inline int getSize() const {return size;} inline int getSize() const {return size;}
inline int getRenderSize() const {return renderSize;} inline int getRenderSize() const {return renderSize;}
int getHeight() const {return height;} int getHeight() const {return height;}
int getStoredResourceCount() const {return (int)storedResources.size();} int getStoredResourceCount() const {return (int)storedResources.size();}
inline const Resource *getStoredResource(int i) const {return &storedResources[i];} 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; bool getCellMapCell(int x, int y, CardinalDir facing) const;
inline bool getMeetingPoint() const {return meetingPoint;} inline bool getMeetingPoint() const {return meetingPoint;}
inline bool getCountUnitDeathInStats() const {return countUnitDeathInStats;} inline bool getCountUnitDeathInStats() const {return countUnitDeathInStats;}

View File

@ -169,6 +169,19 @@ void UpgradeTypeBase::load(const XmlNode *upgradeNode, string upgradename) {
else { else {
prodSpeed = 0; 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 { 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 { int UpgradeTypeBase::getProdSpeed(const SkillType *st) const {
if(prodSpeedIsMultiplier == false || st == NULL) { if(prodSpeedIsMultiplier == false || st == NULL) {
return prodSpeed; return prodSpeed;
@ -347,6 +374,18 @@ string UpgradeTypeBase::getDesc(bool translatedValue) const{
str+= indent+lang.getString("ProductionSpeed",(translatedValue == true ? "" : "english")) + " +" + intToStr(prodSpeed); 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 != "") { if(str != "") {
str += "\n"; str += "\n";
} }
@ -821,6 +860,9 @@ void TotalUpgrade::reset() {
prodSpeed=0; prodSpeed=0;
prodSpeedIsMultiplier=false; prodSpeedIsMultiplier=false;
attackSpeed=0;
attackSpeedIsMultiplier=false;
} }
void TotalUpgrade::sum(const UpgradeTypeBase *ut, const Unit *unit) { 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(); attackRangeIsMultiplier = ut->getAttackRangeIsMultiplier();
moveSpeedIsMultiplier = ut->getMoveSpeedIsMultiplier(); moveSpeedIsMultiplier = ut->getMoveSpeedIsMultiplier();
prodSpeedIsMultiplier = ut->getProdSpeedIsMultiplier(); prodSpeedIsMultiplier = ut->getProdSpeedIsMultiplier();
attackSpeedIsMultiplier = ut->getAttackSpeedIsMultiplier();
if(ut->getMaxHpIsMultiplier() == true) { if(ut->getMaxHpIsMultiplier() == true) {
//printf("#1 Maxhp maxHp = %d, unit->getHp() = %d ut->getMaxHp() = %d\n",maxHp,unit->getHp(),ut->getMaxHp()); //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 { else {
prodSpeed += ut->getProdSpeed(NULL); 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) { 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); prodSpeed -= ut->getProdSpeed(NULL);
enforceMinimumValue(0,prodSpeed); 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) { void TotalUpgrade::incLevel(const UnitType *ut) {
@ -1184,6 +1257,16 @@ void TotalUpgrade::saveGame(XmlNode *rootNode) const {
prodSpeedMorphIsMultiplierValueListNode->addAttribute("key",iterMap->first, mapTagReplacements); prodSpeedMorphIsMultiplierValueListNode->addAttribute("key",iterMap->first, mapTagReplacements);
prodSpeedMorphIsMultiplierValueListNode->addAttribute("value",intToStr(iterMap->second), 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) { void TotalUpgrade::loadGame(const XmlNode *rootNode) {
@ -1282,6 +1365,16 @@ void TotalUpgrade::loadGame(const XmlNode *rootNode) {
prodSpeedMorphIsMultiplierValueList[node->getAttribute("key")->getValue()] = prodSpeedMorphIsMultiplierValueList[node->getAttribute("key")->getValue()] =
node->getAttribute("value")->getIntValue(); 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 // 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_ #ifndef _GLEST_GAME_UPGRADETYPE_H_
#define _GLEST_GAME_UPGRADETYPE_H_ #define _GLEST_GAME_UPGRADETYPE_H_
@ -39,10 +47,9 @@ class MoveSkillType;
class ProduceSkillType; class ProduceSkillType;
class Faction; class Faction;
// =============================== /**
// class UpgradeTypeBase * Groups all information used for upgrades. Attack boosts also use this class for modifying stats.
// =============================== */
class UpgradeTypeBase { class UpgradeTypeBase {
protected: protected:
string upgradename; string upgradename;
@ -64,23 +71,35 @@ protected:
int attackStrength; int attackStrength;
bool attackStrengthIsMultiplier; 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; std::map<string,int> attackStrengthMultiplierValueList;
int attackRange; int attackRange;
bool attackRangeIsMultiplier; bool attackRangeIsMultiplier;
std::map<string,int> attackRangeMultiplierValueList; std::map<string,int> attackRangeMultiplierValueList; /**< @see #attackStrengthMultiplierValueList */
int moveSpeed; int moveSpeed;
bool moveSpeedIsMultiplier; bool moveSpeedIsMultiplier;
std::map<string,int> moveSpeedIsMultiplierValueList; std::map<string,int> moveSpeedIsMultiplierValueList; /**< @see #attackStrengthMultiplierValueList */
int prodSpeed; int prodSpeed;
bool prodSpeedIsMultiplier; bool prodSpeedIsMultiplier;
std::map<string,int> prodSpeedProduceIsMultiplierValueList; std::map<string,int> prodSpeedProduceIsMultiplierValueList; /**< @see #attackStrengthMultiplierValueList */
std::map<string,int> prodSpeedUpgradeIsMultiplierValueList; std::map<string,int> prodSpeedUpgradeIsMultiplierValueList; /**< @see #attackStrengthMultiplierValueList */
std::map<string,int> prodSpeedMorphIsMultiplierValueList; std::map<string,int> prodSpeedMorphIsMultiplierValueList; /**< @see #attackStrengthMultiplierValueList */
int attackSpeed;
bool attackSpeedIsMultiplier;
std::map<string,int> attackSpeedIsMultiplierValueList;
public: public:
/**
* Creates an UpgradeTypeBase with values such that there are no stat changes.
*/
UpgradeTypeBase() { UpgradeTypeBase() {
maxHp = 0;; maxHp = 0;;
maxHpIsMultiplier = false; maxHpIsMultiplier = false;
@ -127,11 +146,30 @@ public:
bool getMoveSpeedIsMultiplier() const {return moveSpeedIsMultiplier;} bool getMoveSpeedIsMultiplier() const {return moveSpeedIsMultiplier;}
int getProdSpeed(const SkillType *st) const; int getProdSpeed(const SkillType *st) const;
bool getProdSpeedIsMultiplier() const {return prodSpeedIsMultiplier;} 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); 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; 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 toString() const {
std::string result = ""; std::string result = "";
@ -163,9 +201,14 @@ public:
return result; 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; virtual void saveGame(XmlNode *rootNode) const;
static const UpgradeType * loadGame(const XmlNode *rootNode, Faction *faction); static const UpgradeType * loadGame(const XmlNode *rootNode, Faction *faction);
/**
* Generates a checksum value for the upgrade.
*/
Checksum getCRC() { Checksum getCRC() {
Checksum crcForUpgradeType; Checksum crcForUpgradeType;
@ -207,58 +250,145 @@ public:
crcForUpgradeType.addInt64((int64)prodSpeedUpgradeIsMultiplierValueList.size()); crcForUpgradeType.addInt64((int64)prodSpeedUpgradeIsMultiplierValueList.size());
//std::map<string,int> prodSpeedMorphIsMultiplierValueList; //std::map<string,int> prodSpeedMorphIsMultiplierValueList;
crcForUpgradeType.addInt64((int64)prodSpeedMorphIsMultiplierValueList.size()); crcForUpgradeType.addInt64((int64)prodSpeedMorphIsMultiplierValueList.size());
crcForUpgradeType.addInt(attackSpeed);
crcForUpgradeType.addInt(attackSpeedIsMultiplier);
return crcForUpgradeType; 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 { class UpgradeType: public UpgradeTypeBase, public ProducibleType {
private: private:
/**
* List of unit types (the "classes" of units, eg, swordman) that are affected by this upgrade.
*/
vector<const UnitType*> effects; vector<const UnitType*> effects;
public: 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); 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, void load(const string &dir, const TechTree *techTree,
const FactionType *factionType, Checksum* checksum, const FactionType *factionType, Checksum* checksum,
Checksum* techtreeChecksum, Checksum* techtreeChecksum,
std::map<string,vector<pair<string, string> > > &loadedFileList, std::map<string,vector<pair<string, string> > > &loadedFileList,
bool validationMode=false); 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; 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();} 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];} 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; 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 string getReqDesc(bool translatedValue) const;
//virtual void saveGame(XmlNode *rootNode) const; //virtual void saveGame(XmlNode *rootNode) const;
//virtual void loadGame(const XmlNode *rootNode); //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 { class TotalUpgrade: public UpgradeTypeBase {
public: public:
TotalUpgrade(); TotalUpgrade();
virtual ~TotalUpgrade() {} virtual ~TotalUpgrade() {}
/**
* Resets all stat boosts (so there's effectively no upgrade).
*/
void reset(); 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); 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); void incLevel(const UnitType *ut);
/**
* Applies the upgrade. Just a delegate to TotalUpgrade::sum.
*/
void apply(const UpgradeTypeBase *ut, const Unit *unit); 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); 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; 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); void loadGame(const XmlNode *rootNode);
}; };

View File

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

View File

@ -21,6 +21,7 @@
#include "network_manager.h" #include "network_manager.h"
#include "object.h" #include "object.h"
#include "particle_type.h" #include "particle_type.h"
#include "projectile_type.h"
#include "path_finder.h" #include "path_finder.h"
#include "renderer.h" #include "renderer.h"
#include "sound.h" #include "sound.h"
@ -127,16 +128,18 @@ bool UnitUpdater::updateUnit(Unit *unit) {
//play skill sound //play skill sound
const SkillType *currSkill= unit->getCurrSkill(); 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(soundStartTime >= unit->getLastAnimProgressAsFloat() && soundStartTime < unit->getAnimProgressAsFloat()) {
if(map->getSurfaceCell(Map::toSurfCoords(unit->getPos()))->isVisible(world->getThisTeamIndex()) || if(map->getSurfaceCell(Map::toSurfCoords(unit->getPos()))->isVisible(world->getThisTeamIndex()) ||
(game->getWorld()->showWorldForPlayer(game->getWorld()->getThisTeamIndex()) == true)) { (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()) { if (currSkill->getShake()) {
float shakeStartTime = currSkill->getShakeStartTime(); float shakeStartTime = currSkill->getShakeStartTime();
if (shakeStartTime >= unit->getLastAnimProgressAsFloat() if (shakeStartTime >= unit->getLastAnimProgressAsFloat()
@ -186,14 +189,24 @@ bool UnitUpdater::updateUnit(Unit *unit) {
float attackStartTime = truncateDecimal<float>(ast->getAttackStartTime(),6); float attackStartTime = truncateDecimal<float>(ast->getAttackStartTime(),6);
float lastAnimProgress = truncateDecimal<float>(unit->getLastAnimProgressAsFloat(),6); float lastAnimProgress = truncateDecimal<float>(unit->getLastAnimProgressAsFloat(),6);
float animProgress = truncateDecimal<float>(unit->getAnimProgressAsFloat(),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]=""; char szBuf[8096]="";
snprintf(szBuf,8095,"attackStartTime = %f, lastAnimProgress = %f, animProgress = %f startAttackParticleSystemNow = %d",attackStartTime,lastAnimProgress,animProgress,startAttackParticleSystemNow); snprintf(szBuf,8095,"attackStartTime = %f, lastAnimProgress = %f, animProgress = %f startAttackParticleSystemNow = %d",attackStartTime,lastAnimProgress,animProgress,startAttackParticleSystemNow);
unit->setNetworkCRCParticleLogInfo(szBuf); unit->setNetworkCRCParticleLogInfo(szBuf);
if(startAttackParticleSystemNow == true) { if(startAttackParticleSystemNow == true) {
startAttackParticleSystem(unit); startAttackParticleSystem(unit,lastAnimProgress,animProgress);
} }
} }
@ -257,55 +270,12 @@ bool UnitUpdater::updateUnit(Unit *unit) {
else if(unit->getCommandSize() > 0) { else if(unit->getCommandSize() > 0) {
Command *command= unit->getCurrCommand(); Command *command= unit->getCurrCommand();
if(command != NULL) { if(command != NULL) {
const CommandType *ct = command->getCommandType();
const AttackCommandType *act= dynamic_cast<const AttackCommandType*>(command->getCommandType()); const AttackCommandType *act= dynamic_cast<const AttackCommandType*>(command->getCommandType());
if( act != NULL && act->getAttackSkillType() != NULL && if (act != NULL && act->getAttackSkillType() != NULL
act->getAttackSkillType()->getSpawnUnit() != "" && act->getAttackSkillType()->getSpawnUnitCount() > 0) { && act->getAttackSkillType()->getSpawnUnit() != ""
&& act->getAttackSkillType()->getSpawnUnitCount() > 0) {
const FactionType *ft= unit->getFaction()->getType(); spawnAttack(unit,act->getAttackSkillType()->getSpawnUnit(),act->getAttackSkillType()->getSpawnUnitCount(),act->getAttackSkillType()->getSpawnUnitAtTarget());
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());
}
}
} }
} }
} }
@ -343,6 +313,65 @@ bool UnitUpdater::updateUnit(Unit *unit) {
return processUnitCommand; 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 ==================== // ==================== progress commands ====================
//VERY IMPORTANT: compute next state depending on the first order of the list //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 ==================== // ==================== attack ====================
void UnitUpdater::hit(Unit *attacker){ 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 //hit attack positions
if(ast != NULL && ast->getSplash()) { if(ast != NULL && ast->getSplash()) {
char szBuf[8096]=""; char szBuf[8096]="";
@ -2511,7 +2540,7 @@ void UnitUpdater::hit(Unit *attacker, const AttackSkillType* ast, const Vec2i &t
float distance = pci.getPos().dist(targetPos); float distance = pci.getPos().dist(targetPos);
distance = truncateDecimal<float>(distance,6); 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); attacker->addNetworkCRCDecHp(szBuf);
if(attacked != NULL) { 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) { if(attacker == NULL) {
throw megaglest_runtime_error("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 *= damageMultiplier;
damage = truncateDecimal<float>(damage,6); damage = truncateDecimal<float>(damage,6);
damage = (damage*damagePercent)/100;
if(damage < 1) { if(damage < 1) {
damage= 1; damage= 1;
} }
@ -2573,6 +2603,37 @@ void UnitUpdater::damage(Unit *attacker, const AttackSkillType* ast, Unit *attac
attacker->incKills(attacked->getTeam()); 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()) { switch(this->game->getGameSettings()->getPathFinderType()) {
case pfBasic: case pfBasic:
break; break;
@ -2592,18 +2653,18 @@ void UnitUpdater::damage(Unit *attacker, const AttackSkillType* ast, Unit *attac
//attacker->computeHp(); //attacker->computeHp();
} }
void UnitUpdater::startAttackParticleSystem(Unit *unit){ void UnitUpdater::startAttackParticleSystem(Unit *unit, float lastAnimProgress, float animProgress){
Renderer &renderer= Renderer::getInstance(); 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) { if(ast == NULL) {
throw megaglest_runtime_error("Start attack particle 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 startPos= unit->getCurrVector();
Vec3f endPos= unit->getTargetVec(); Vec3f endPos= unit->getTargetVec();
@ -2615,39 +2676,51 @@ void UnitUpdater::startAttackParticleSystem(Unit *unit){
visible = true; visible = true;
} }
//projectile //for(ProjectileParticleSystemTypes::const_iterator pit= unit->getCurrSkill()->projectileParticleSystemTypes.begin(); pit != unit->getCurrSkill()->projectileParticleSystemTypes.end(); ++pit) {
if(pstProj != NULL) { for(ProjectileTypes::const_iterator pt= ast->projectileTypes.begin(); pt != ast->projectileTypes.end(); ++pt) {
psProj= pstProj->create(unit); bool startAttackParticleSystemNow = ((*pt)->getAttackStartTime() >= lastAnimProgress && (*pt)->getAttackStartTime() < animProgress);
psProj->setPath(startPos, endPos); if(startAttackParticleSystemNow){
psProj->setObserver(new ParticleDamager(unit, this, gameCamera)); ProjectileParticleSystem *psProj= (*pt)->getProjectileParticleSystemType()->create(unit);
psProj->setVisible(visible); psProj->setPath(startPos, endPos);
if(unit->getFaction()->getTexture()) { psProj->setObserver(new ParticleDamager(unit,(*pt), this, gameCamera));
psProj->setFactionColor(unit->getFaction()->getTexture()->getPixmapConst()->getPixel3f(0,0)); 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]=""; char szBuf[8096]="";
snprintf(szBuf,8095,"Unit hitting [startAttackParticleSystem] no proj"); snprintf(szBuf,8095,"Unit hitting [startAttackParticleSystem] no proj");
unit->addNetworkCRCDecHp(szBuf); unit->addNetworkCRCDecHp(szBuf);
hit(unit); hit(unit);
} //splash
if(pstSplash != NULL) {
//splash SplashParticleSystem *psSplash= pstSplash->create(unit);
if(pstSplash != NULL) { psSplash->setPos(endPos);
SplashParticleSystem *psSplash= pstSplash->create(unit); psSplash->setVisible(visible);
psSplash->setPos(endPos); if(unit->getFaction()->getTexture()) {
psSplash->setVisible(visible); psSplash->setFactionColor(unit->getFaction()->getTexture()->getPixmapConst()->getPixel3f(0,0));
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 // 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->gameCamera= gameCamera;
this->attackerRef= attacker; this->attackerRef= attacker;
this->projectileType= projectileType;
this->ast= static_cast<const AttackSkillType*>(attacker->getCurrSkill()); this->ast= static_cast<const AttackSkillType*>(attacker->getCurrSkill());
this->targetPos= attacker->getTargetPos(); this->targetPos= attacker->getTargetPos();
this->targetField= attacker->getTargetField(); 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); snprintf(szBuf,8095,"Unit hitting [ParticleDamager::update] [%s] targetField = %d",targetPos.getString().c_str(),targetField);
attacker->addNetworkCRCDecHp(szBuf); attacker->addNetworkCRCDecHp(szBuf);
unitUpdater->hit(attacker, ast, targetPos, targetField); unitUpdater->hit(attacker, ast, targetPos, targetField, projectileType->getDamagePercentage());
//char szBuf[8096]=""; //char szBuf[8096]="";
//snprintf(szBuf,8095,"ParticleDamager::update attacker particleSystem before: %s\nafter: %s",auditBeforeHit.c_str(),particleSystem->toString().c_str()); //snprintf(szBuf,8095,"ParticleDamager::update attacker particleSystem before: %s\nafter: %s",auditBeforeHit.c_str(),particleSystem->toString().c_str());
//attacker->setNetworkCRCParticleObserverLogInfo(szBuf); //attacker->setNetworkCRCParticleObserverLogInfo(szBuf);
//play sound //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) { if(particleSystem->getVisible() && projSound != NULL) {
SoundRenderer::getInstance().playFx(projSound, attacker->getCurrVector(), gameCamera->getPos()); 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); particleSystem->setObserver(NULL);
delete this; delete this;

View File

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

View File

@ -49,6 +49,8 @@ public:
Vec3f pos; Vec3f pos;
Vec3f lastPos; Vec3f lastPos;
Vec3f speed; Vec3f speed;
float speedUpRelative;
Vec3f speedUpConstant;
Vec3f accel; Vec3f accel;
Vec4f color; Vec4f color;
float size; float size;
@ -147,6 +149,8 @@ protected:
int varParticleEnergy; int varParticleEnergy;
float particleSize; float particleSize;
float speed; float speed;
float speedUpRelative;
float speedUpConstant;
Vec3f factionColor; Vec3f factionColor;
bool teamcolorNoEnergy; bool teamcolorNoEnergy;
bool teamcolorEnergy; bool teamcolorEnergy;
@ -192,6 +196,8 @@ public:
void setVarParticleEnergy(int varParticleEnergy); void setVarParticleEnergy(int varParticleEnergy);
void setParticleSize(float particleSize); void setParticleSize(float particleSize);
void setSpeed(float speed); void setSpeed(float speed);
void setSpeedUpRelative(float speedUpRelative);
void setSpeedUpConstant(float speedUpConstant);
virtual void setActive(bool active); virtual void setActive(bool active);
void setObserver(ParticleObserver *particleObserver); void setObserver(ParticleObserver *particleObserver);
virtual void setVisible(bool visible); 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 endPathWithSlash(string &path, bool requireOSSlash=false);
void trimPathWithStartingSlash(string &path); void trimPathWithStartingSlash(string &path);
void updatePathClimbingParts(string &path); void updatePathClimbingParts(string &path,bool processPreviousDirTokenCheck=true);
string formatPath(string path); string formatPath(string path);
string replaceAllHTMLEntities(string& context); string replaceAllHTMLEntities(string& context);

View File

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

View File

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

View File

@ -50,6 +50,10 @@ void Particle::saveGame(XmlNode *rootNode) {
particleNode->addAttribute("lastPos",lastPos.getString(), mapTagReplacements); particleNode->addAttribute("lastPos",lastPos.getString(), mapTagReplacements);
// Vec3f speed; // Vec3f speed;
particleNode->addAttribute("speed",speed.getString(), mapTagReplacements); 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; // Vec3f accel;
particleNode->addAttribute("accel",accel.getString(), mapTagReplacements); particleNode->addAttribute("accel",accel.getString(), mapTagReplacements);
// Vec4f color; // Vec4f color;
@ -70,6 +74,10 @@ void Particle::loadGame(const XmlNode *rootNode) {
lastPos = Vec3f::strToVec3(particleNode->getAttribute("lastPos")->getValue()); lastPos = Vec3f::strToVec3(particleNode->getAttribute("lastPos")->getValue());
// Vec3f speed; // Vec3f speed;
speed = Vec3f::strToVec3(particleNode->getAttribute("speed")->getValue()); 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; // Vec3f accel;
accel = Vec3f::strToVec3(particleNode->getAttribute("accel")->getValue()); accel = Vec3f::strToVec3(particleNode->getAttribute("accel")->getValue());
// Vec4f color; // Vec4f color;
@ -290,6 +298,16 @@ void ParticleSystem::setSpeed(float speed){
this->speed = truncateDecimal<float>(this->speed,6); 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){ void ParticleSystem::setActive(bool active){
this->active= active; this->active= active;
for(int i=getChildCount()-1; i>=0; i--) for(int i=getChildCount()-1; i>=0; i--)
@ -1114,6 +1132,7 @@ void UnitParticleSystem::initParticle(Particle *p, int particleIndex){
p->lastPos= pos; p->lastPos= pos;
oldPosition= pos; oldPosition= pos;
p->size= particleSize; p->size= particleSize;
p->speedUpRelative= speedUpRelative;
p->accel= Vec3f(0.0f, -gravity, 0.0f); p->accel= Vec3f(0.0f, -gravity, 0.0f);
p->accel.x = truncateDecimal<float>(p->accel.x,6); p->accel.x = truncateDecimal<float>(p->accel.x,6);
p->accel.y = truncateDecimal<float>(p->accel.y,6); p->accel.y = truncateDecimal<float>(p->accel.y,6);
@ -1228,6 +1247,8 @@ void UnitParticleSystem::initParticle(Particle *p, int particleIndex){
} break; } break;
default: throw megaglest_runtime_error("bad shape"); 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(){ void UnitParticleSystem::update(){
@ -1299,6 +1320,8 @@ void UnitParticleSystem::updateParticle(Particle *p){
p->pos.z = truncateDecimal<float>(p->pos.z,6); p->pos.z = truncateDecimal<float>(p->pos.z,6);
} }
p->speed += p->accel; 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.x = truncateDecimal<float>(p->speed.x,6);
p->speed.y = truncateDecimal<float>(p->speed.y,6); p->speed.y = truncateDecimal<float>(p->speed.y,6);
p->speed.z = truncateDecimal<float>(p->speed.z,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->energy= maxParticleEnergy;
p->size= particleSize; p->size= particleSize;
p->color= color; p->color= color;
p->speedUpRelative= speedUpRelative;
p->speed= Vec3f(horizontalSpreadA * random.randRange(-1.0f, 1.0f) + horizontalSpreadB, verticalSpreadA 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) * 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.y = truncateDecimal<float>(p->accel.y,6);
p->accel.z = truncateDecimal<float>(p->accel.z,6); p->accel.z = truncateDecimal<float>(p->accel.z,6);
p->speedUpConstant= Vec3f(speedUpConstant)*p->speed;
} }
void SplashParticleSystem::updateParticle(Particle *p){ 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.y = truncateDecimal<float>(p->pos.y,6);
p->pos.z = truncateDecimal<float>(p->pos.z,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= p->speed + p->accel;
p->speed.x = truncateDecimal<float>(p->speed.x,6); p->speed.x = truncateDecimal<float>(p->speed.x,6);
p->speed.y = truncateDecimal<float>(p->speed.y,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 /./ // Update paths with /./
string::size_type pos = path.find("/./"); string::size_type pos = path.find("/./");
if(pos != string::npos && pos != 0) { if(pos != string::npos && pos != 0) {
@ -569,9 +569,11 @@ void updatePathClimbingParts(string &path) {
path.erase(pos,2); path.erase(pos,2);
//pos--; //pos--;
//printf("#1 CHANGE relative path from [%s] to [%s]\n",orig.c_str(),path.c_str());
pos = path.find("/./"); pos = path.find("/./");
if(pos != string::npos && pos != 0) { 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()); 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; string orig = path;
path.erase(pos,2); path.erase(pos,2);
//pos--; //pos--;
//printf("#w CHANGE relative path from [%s] to [%s]\n",orig.c_str(),path.c_str());
pos = path.find("\\.\\"); pos = path.find("\\.\\");
if(pos != string::npos && pos != 0) { 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()); if(SystemFlags::VERBOSE_MODE_ENABLED) printf("CHANGED relative path from [%s] to [%s]\n",orig.c_str(),path.c_str());
} }
// Update paths with .. // Update paths with ..
pos = path.find(".."); if(processPreviousDirTokenCheck) {
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;
}
}
pos = path.find(".."); pos = path.find("..");
if(pos != string::npos && pos != 0) { 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") ) // if ( !strcmp (params[1], "quit") )
irc_cmd_quit (session, "of course, Master!"); // irc_cmd_quit (session, "of course, Master!");
//
if ( !strcmp (params[1], "help") ) { // if ( !strcmp (params[1], "help") ) {
irc_cmd_msg (session, params[0], "quit, help, dcc chat, dcc send, ctcp"); // irc_cmd_msg (session, params[0], "quit, help, dcc chat, dcc send, ctcp");
} // }
//
if ( !strcmp (params[1], "ctcp") ) { // if ( !strcmp (params[1], "ctcp") ) {
irc_cmd_ctcp_request (session, realNick, "PING 223"); // irc_cmd_ctcp_request (session, realNick, "PING 223");
irc_cmd_ctcp_request (session, realNick, "FINGER"); // irc_cmd_ctcp_request (session, realNick, "FINGER");
irc_cmd_ctcp_request (session, realNick, "VERSION"); // irc_cmd_ctcp_request (session, realNick, "VERSION");
irc_cmd_ctcp_request (session, realNick, "TIME"); // irc_cmd_ctcp_request (session, realNick, "TIME");
} // }
//
if ( !strcmp (params[1], "dcc chat") ) { // if ( !strcmp (params[1], "dcc chat") ) {
irc_dcc_t dccid; // irc_dcc_t dccid;
irc_dcc_chat (session, 0, realNick, dcc_recv_callback, &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(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("DCC chat ID: %d\n", dccid);
} // }
//
if ( !strcmp (params[1], "dcc send") ) { // if ( !strcmp (params[1], "dcc send") ) {
irc_dcc_t dccid; // irc_dcc_t dccid;
irc_dcc_sendfile (session, 0, realNick, "irctest.c", dcc_file_recv_callback, &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(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("DCC send ID: %d\n", dccid);
} // }
//
if ( !strcmp (params[1], "topic") ) { // if ( !strcmp (params[1], "topic") ) {
irc_cmd_topic (session, params[0], 0); // irc_cmd_topic (session, params[0], 0);
} // }
else if ( strstr (params[1], "topic ") == params[1] ) { // else if ( strstr (params[1], "topic ") == params[1] ) {
irc_cmd_topic (session, params[0], params[1] + 6); // irc_cmd_topic (session, params[0], params[1] + 6);
} // }
//
if ( strstr (params[1], "mode ") == params[1] ) // if ( strstr (params[1], "mode ") == params[1] )
irc_cmd_channel_mode (session, params[0], params[1] + 5); // irc_cmd_channel_mode (session, params[0], params[1] + 5);
//
if ( strstr (params[1], "nick ") == params[1] ) // if ( strstr (params[1], "nick ") == params[1] )
irc_cmd_nick (session, params[1] + 5); // irc_cmd_nick (session, params[1] + 5);
//
if ( strstr (params[1], "whois ") == params[1] ) // if ( strstr (params[1], "whois ") == params[1] )
irc_cmd_whois (session, params[1] + 5); // 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) { 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; return false;
} }
void Properties::updateValuePathVariable(string &value) { void Properties::updateValuePathVariable(string &value, bool skipUpdatePathClimbingParts) {
replaceAll(value,"//","/"); replaceAll(value,"//","/");
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; string originalValue = value;
bool valueRequiresPathUpdate = Properties::isValuePathVariable(value); bool valueRequiresPathUpdate = Properties::isValuePathVariable(value);
//if(originalValue.find("$APPLICATIONDATAPATH") != string::npos) { //if(originalValue.find("$APPLICATIONDATAPATH") != string::npos) {
@ -389,7 +391,7 @@ bool Properties::applyTagsToValue(string &value, const std::map<string,string> *
//} //}
if(valueRequiresPathUpdate == true) { if(valueRequiresPathUpdate == true) {
Properties::updateValuePathVariable(value); Properties::updateValuePathVariable(value, skipUpdatePathClimbingParts);
} }
return (originalValue != value); return (originalValue != value);
} }

View File

@ -339,7 +339,8 @@ XmlIoRapid::~XmlIoRapid() {
cleanup(); 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; bool showPerfStats = SystemFlags::VERBOSE_MODE_ENABLED;
Chrono chrono; Chrono chrono;
chrono.start(); chrono.start();
@ -388,7 +389,7 @@ XmlNode *XmlIoRapid::load(const string &path, const std::map<string,string> &map
// Load data and add terminating 0 // Load data and add terminating 0
vector<char> buffer; 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)); xmlFile.read(&buffer.front(), static_cast<streamsize>(file_size));
buffer[(unsigned int)file_size] = 0; 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()); 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()); 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->engine_type = engine_type;
this->skipStackCheck = false; this->skipStackCheck = false;
this->skipUpdatePathClimbingParts = false;
} }
void XmlTree::init(const string &name){ void XmlTree::init(const string &name){
@ -533,6 +535,10 @@ typedef std::vector<XmlTree*> LoadStack;
//static LoadStack loadStack; //static LoadStack loadStack;
static string loadStackCacheName = string(__FILE__) + string("_loadStackCacheName"); 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) { 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); 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 else
#endif #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()); 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 #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) { if(node == NULL || node->name() == NULL) {
throw megaglest_runtime_error("XML structure seems to be corrupt!"); 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(); for(xml_node<> *currentNode = node->first_node();
currentNode; currentNode = currentNode->next_sibling()) { currentNode; currentNode = currentNode->next_sibling()) {
if(currentNode != NULL && currentNode->type() == node_element) { if(currentNode != NULL && currentNode->type() == node_element) {
XmlNode *xmlNode= new XmlNode(currentNode, mapTagReplacementValues); XmlNode *xmlNode= new XmlNode(currentNode, mapTagReplacementValues, skipUpdatePathClimbingParts);
children.push_back(xmlNode); children.push_back(xmlNode);
} }
} }
@ -696,8 +703,18 @@ XmlNode::XmlNode(xml_node<> *node, const std::map<string,string> &mapTagReplacem
//get value //get value
if(node->type() == node_element && children.size() == 0) { if(node->type() == node_element && children.size() == 0) {
text = node->value(); string xmlText = node->value();
Properties::applyTagsToValue(this->text,&mapTagReplacementValues);
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;
} }
} }