mirror of
https://github.com/vcmi/vcmi.git
synced 2024-12-24 22:14:36 +02:00
Merge tag '0.99'
# Conflicts: # debian/changelog # lib/GameConstants.h
This commit is contained in:
commit
258202d682
8
.gitignore
vendored
8
.gitignore
vendored
@ -13,6 +13,9 @@
|
||||
*.layout
|
||||
*.pro.user
|
||||
*.pro.user.*
|
||||
*.swp
|
||||
*.h.gch
|
||||
*~
|
||||
/CMakeLists.txt.user
|
||||
CMakeCache.txt
|
||||
CMakeFiles
|
||||
@ -28,3 +31,8 @@ ui_*.h
|
||||
/CPackSourceConfig.cmake
|
||||
build-*
|
||||
CMakeLists.txt.user.*
|
||||
Doxyfile
|
||||
doc/*
|
||||
VCMI_VS11.sdf
|
||||
*.ipch
|
||||
VCMI_VS11.opensdf
|
||||
|
26
.travis.linux
Normal file
26
.travis.linux
Normal file
@ -0,0 +1,26 @@
|
||||
#!/bin/sh
|
||||
|
||||
#new Clang
|
||||
sudo add-apt-repository --yes ppa:h-rayflood/llvm
|
||||
|
||||
#new SDL2
|
||||
sudo add-apt-repository --yes ppa:zoogie/sdl2-snapshots
|
||||
|
||||
#new Qt
|
||||
sudo add-apt-repository --yes ppa:beineri/opt-qt57-trusty
|
||||
|
||||
#new CMake
|
||||
sudo add-apt-repository --yes ppa:george-edison55/cmake-3.x
|
||||
|
||||
sudo apt-get update -qq
|
||||
|
||||
sudo apt-get install -qq $SUPPORT
|
||||
sudo apt-get install -qq $PACKAGE
|
||||
sudo apt-get install -qq cmake libboost1.54-all-dev zlib1g-dev
|
||||
sudo apt-get install -qq libsdl2-dev libsdl2-image-dev libsdl2-mixer-dev libsdl2-ttf-dev
|
||||
sudo apt-get install -qq libavformat-dev libswscale-dev
|
||||
sudo apt-get install -qq qt57declarative
|
||||
|
||||
#setup compiler
|
||||
source /opt/qt57/bin/qt57-env.sh
|
||||
export CC=${REAL_CC} CXX=${REAL_CXX}
|
17
.travis.osx
Normal file
17
.travis.osx
Normal file
@ -0,0 +1,17 @@
|
||||
#!/bin/sh
|
||||
|
||||
# https://gist.github.com/vmarkovtsev/3f2dd98e56cb63098027
|
||||
|
||||
brew unlink boost
|
||||
brew install boost smpeg2 innoextract libpng freetype sdl2 sdl2_ttf sdl2_image qt5 ffmpeg
|
||||
brew install sdl2_mixer --with-smpeg2
|
||||
sudo sed -i.bak 's/106200/106900/g' /usr/local/Cellar/cmake/*/share/cmake/Modules/FindBoost.cmake
|
||||
|
||||
export CMAKE_PREFIX_PATH="/usr/local/opt/qt5:$CMAKE_PREFIX_PATH"
|
||||
|
||||
sparkle_version=$(curl -L https://github.com/sparkle-project/Sparkle/releases/latest | grep '<span class="css-truncate-target">' | sed -E 's|^.*([1-9]\.[0-9]+\.[0-9]+).*$|\1|g')
|
||||
wget https://github.com/sparkle-project/Sparkle/releases/download/$sparkle_version/Sparkle-$sparkle_version.tar.bz2
|
||||
mkdir sparkle && cd sparkle
|
||||
tar -xf ../Sparkle-*.tar.bz2
|
||||
sudo mv Sparkle.framework /Library/Frameworks/
|
||||
cd .. && rm -rf sparkle
|
60
.travis.yml
60
.travis.yml
@ -1,39 +1,22 @@
|
||||
language: cpp
|
||||
os:
|
||||
- linux
|
||||
- osx
|
||||
dist: trusty
|
||||
sudo: required
|
||||
|
||||
before_install:
|
||||
#new boost
|
||||
- sudo add-apt-repository --yes ppa:boost-latest/ppa
|
||||
#new GCC
|
||||
- sudo add-apt-repository --yes ppa:ubuntu-toolchain-r/test
|
||||
#new Clang
|
||||
- sudo add-apt-repository --yes ppa:h-rayflood/llvm
|
||||
#new SDL2
|
||||
- sudo add-apt-repository --yes ppa:zoogie/sdl2-snapshots
|
||||
#new Qt
|
||||
- sudo add-apt-repository --yes ppa:beineri/opt-qt532
|
||||
#new CMake
|
||||
- sudo add-apt-repository --yes ppa:andykimpe/cmake
|
||||
|
||||
- sudo apt-get update -qq
|
||||
|
||||
- sudo apt-get install -qq $SUPPORT
|
||||
- sudo apt-get install -qq $PACKAGE
|
||||
- sudo apt-get install -qq cmake libboost1.55-all-dev zlib1g-dev
|
||||
- sudo apt-get install -qq libsdl2-dev libsdl2-image-dev libsdl2-mixer-dev libsdl2-ttf-dev
|
||||
- sudo apt-get install -qq libavformat-dev libswscale-dev
|
||||
- sudo apt-get install -qq qt53declarative
|
||||
|
||||
#setup compiler
|
||||
- source /opt/qt53/bin/qt53-env.sh
|
||||
- export CC=${REAL_CC} CXX=${REAL_CXX}
|
||||
- if [[ $TRAVIS_OS_NAME == 'linux' ]]; then . .travis.linux; fi
|
||||
- if [[ $TRAVIS_OS_NAME == 'osx' ]]; then . .travis.osx; fi
|
||||
|
||||
before_script:
|
||||
- mkdir build
|
||||
- cd build
|
||||
- cmake ..
|
||||
- cmake -G "Unix Makefiles" ..
|
||||
|
||||
script:
|
||||
- make
|
||||
- if [[ $TRAVIS_OS_NAME == 'osx' ]]; then cd ..; xcodebuild -project osx/osx-vcmibuilder/vcmibuilder.xcodeproj/ -configuration Release CONFIGURATION_BUILD_DIR=..; cd build; fi
|
||||
- make -j2
|
||||
|
||||
env:
|
||||
- ignore=this
|
||||
@ -42,16 +25,19 @@ matrix:
|
||||
exclude:
|
||||
- env: ignore=this
|
||||
include:
|
||||
- compiler: clang # fails all the time - missing packages?
|
||||
env: REAL_CC=clang-3.2 REAL_CXX=clang++-3.2 PACKAGE=clang-3.2 SUPPORT=g++-4.8
|
||||
- compiler: clang
|
||||
env: REAL_CC=clang-3.3 REAL_CXX=clang++-3.3 PACKAGE=clang-3.3 SUPPORT=g++-4.8
|
||||
- compiler: clang
|
||||
env: REAL_CC=clang-3.4 REAL_CXX=clang++-3.4 PACKAGE=clang-3.4 SUPPORT=g++-4.8
|
||||
#- compiler: gcc # fails due to running out of memory - vcmi need too much of it for successfull compilation
|
||||
# env: REAL_CC=gcc-4.7 REAL_CXX=g++-4.7 PACKAGE=g++-4.7 SUPPORT=
|
||||
#- compiler: gcc # same as 4.7
|
||||
# env: REAL_CC=gcc-4.8 REAL_CXX=g++-4.8 PACKAGE=g++-4.8 SUPPORT=
|
||||
- os: linux
|
||||
compiler: clang
|
||||
env: REAL_CC=clang-3.4 REAL_CXX=clang++-3.4 PACKAGE=clang-3.4 SUPPORT=libstdc++-4.8-dev
|
||||
- os: linux
|
||||
compiler: clang
|
||||
env: REAL_CC=clang-3.5 REAL_CXX=clang++-3.5 PACKAGE=clang-3.5 SUPPORT=libstdc++-4.8-dev
|
||||
- os: linux
|
||||
compiler: clang
|
||||
env: REAL_CC=clang-3.6 REAL_CXX=clang++-3.6 PACKAGE=clang-3.6 SUPPORT=libstdc++-4.8-dev
|
||||
- os: linux
|
||||
compiler: gcc
|
||||
env: REAL_CC=gcc-4.8 REAL_CXX=g++-4.8 PACKAGE=g++-4.8 SUPPORT=
|
||||
- os: osx
|
||||
|
||||
notifications:
|
||||
email:
|
||||
|
@ -6,43 +6,23 @@
|
||||
<Option pch_mode="2" />
|
||||
<Option compiler="gcc" />
|
||||
<Build>
|
||||
<Target title="Debug-win32-SDL2">
|
||||
<Target title="Debug-win32">
|
||||
<Option platforms="Windows;" />
|
||||
<Option output="../BattleAI" imp_lib="$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).a" def_file="$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).def" prefix_auto="1" extension_auto="1" />
|
||||
<Option object_output="obj/Debug/" />
|
||||
<Option object_output="obj/Debug/x86/" />
|
||||
<Option type="3" />
|
||||
<Option compiler="gcc" />
|
||||
<Compiler>
|
||||
<Add option="-g" />
|
||||
</Compiler>
|
||||
</Target>
|
||||
<Target title="Release-win32-SDL2">
|
||||
<Option platforms="Windows;" />
|
||||
<Option output="../BattleAI" imp_lib="$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).a" def_file="$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).def" prefix_auto="1" extension_auto="1" />
|
||||
<Option object_output="obj/Release/" />
|
||||
<Option type="3" />
|
||||
<Option compiler="gcc" />
|
||||
<Compiler>
|
||||
<Add option="-O2" />
|
||||
</Compiler>
|
||||
<Linker>
|
||||
<Add option="-s" />
|
||||
<Add directory="$(#boost.lib32)" />
|
||||
</Linker>
|
||||
</Target>
|
||||
<Target title="Debug-win32-SDL1">
|
||||
<Target title="Release-win32">
|
||||
<Option platforms="Windows;" />
|
||||
<Option output="../BattleAI" imp_lib="$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).a" def_file="$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).def" prefix_auto="1" extension_auto="1" />
|
||||
<Option object_output="obj/Debug/" />
|
||||
<Option type="3" />
|
||||
<Option compiler="gcc" />
|
||||
<Compiler>
|
||||
<Add option="-g" />
|
||||
</Compiler>
|
||||
</Target>
|
||||
<Target title="Release-win32-SDL1">
|
||||
<Option platforms="Windows;" />
|
||||
<Option output="../BattleAI" imp_lib="$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).a" def_file="$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).def" prefix_auto="1" extension_auto="1" />
|
||||
<Option object_output="obj/Release/" />
|
||||
<Option object_output="obj/Release/x86/" />
|
||||
<Option type="3" />
|
||||
<Option compiler="gcc" />
|
||||
<Compiler>
|
||||
@ -50,6 +30,20 @@
|
||||
</Compiler>
|
||||
<Linker>
|
||||
<Add option="-s" />
|
||||
<Add directory="$(#boost.lib32)" />
|
||||
</Linker>
|
||||
</Target>
|
||||
<Target title="Debug-win64">
|
||||
<Option platforms="Windows;" />
|
||||
<Option output="../BattleAI" imp_lib="$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).a" def_file="$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).def" prefix_auto="1" extension_auto="1" />
|
||||
<Option object_output="obj/Debug/x64/" />
|
||||
<Option type="3" />
|
||||
<Option compiler="gnu_gcc_compiler_x64" />
|
||||
<Compiler>
|
||||
<Add option="-g" />
|
||||
</Compiler>
|
||||
<Linker>
|
||||
<Add directory="$(#boost.lib64)" />
|
||||
</Linker>
|
||||
</Target>
|
||||
</Build>
|
||||
@ -57,6 +51,7 @@
|
||||
<Add option="-pedantic" />
|
||||
<Add option="-Wextra" />
|
||||
<Add option="-Wall" />
|
||||
<Add option="-std=gnu++11" />
|
||||
<Add option="-fexceptions" />
|
||||
<Add option="-Wpointer-arith" />
|
||||
<Add option="-Wno-switch" />
|
||||
@ -69,12 +64,12 @@
|
||||
<Linker>
|
||||
<Add option="-lboost_system$(#boost.libsuffix)" />
|
||||
<Add option="-lVCMI_lib" />
|
||||
<Add directory="$(#boost.lib32)" />
|
||||
<Add directory="../.." />
|
||||
</Linker>
|
||||
<Unit filename="BattleAI.cpp" />
|
||||
<Unit filename="BattleAI.h" />
|
||||
<Unit filename="StdInc.h">
|
||||
<Option compile="1" />
|
||||
<Option weight="0" />
|
||||
</Unit>
|
||||
<Unit filename="main.cpp" />
|
||||
|
@ -8,7 +8,7 @@
|
||||
#include "../../lib/VCMI_Lib.h"
|
||||
|
||||
using boost::optional;
|
||||
static shared_ptr<CBattleCallback> cbc;
|
||||
static std::shared_ptr<CBattleCallback> cbc;
|
||||
|
||||
#define LOGL(text) print(text)
|
||||
#define LOGFL(text, formattingEl) print(boost::str(boost::format(text) % formattingEl))
|
||||
@ -91,7 +91,7 @@ CBattleAI::~CBattleAI(void)
|
||||
}
|
||||
}
|
||||
|
||||
void CBattleAI::init(shared_ptr<CBattleCallback> CB)
|
||||
void CBattleAI::init(std::shared_ptr<CBattleCallback> CB)
|
||||
{
|
||||
print("init called, saving ptr to IBattleCallback");
|
||||
cbc = cb = CB;
|
||||
@ -103,11 +103,6 @@ void CBattleAI::init(shared_ptr<CBattleCallback> CB)
|
||||
CB->unlockGsWhenWaiting = false;
|
||||
}
|
||||
|
||||
static bool thereRemainsEnemy()
|
||||
{
|
||||
return !cbc->battleIsFinished();
|
||||
}
|
||||
|
||||
BattleAction CBattleAI::activeStack( const CStack * stack )
|
||||
{
|
||||
LOG_TRACE_PARAMS(logAi, "stack: %s", stack->nodeName()) ;
|
||||
@ -136,21 +131,20 @@ BattleAction CBattleAI::activeStack( const CStack * stack )
|
||||
if(cb->battleCanCastSpell())
|
||||
attemptCastingSpell();
|
||||
|
||||
if(!thereRemainsEnemy())
|
||||
return BattleAction();
|
||||
if(auto ret = cbc->battleIsFinished())
|
||||
{
|
||||
//spellcast may finish battle
|
||||
//send special preudo-action
|
||||
BattleAction cancel;
|
||||
cancel.actionType = Battle::CANCEL;
|
||||
return cancel;
|
||||
}
|
||||
|
||||
if(auto action = considerFleeingOrSurrendering())
|
||||
return *action;
|
||||
|
||||
if(cb->battleGetStacks(CBattleInfoEssentials::ONLY_ENEMY).empty())
|
||||
{
|
||||
//We apparently won battle by casting spell, return defend... (accessing cb may cause trouble)
|
||||
return BattleAction::makeDefend(stack);
|
||||
}
|
||||
|
||||
PotentialTargets targets(stack);
|
||||
|
||||
|
||||
if(targets.possibleAttacks.size())
|
||||
{
|
||||
auto hlp = targets.bestAction();
|
||||
@ -165,7 +159,7 @@ BattleAction CBattleAI::activeStack( const CStack * stack )
|
||||
{
|
||||
ThreatMap threatsToUs(stack);
|
||||
auto dists = cbc->battleGetDistances(stack);
|
||||
const EnemyInfo &ei= *range::min_element(targets.unreachableEnemies, std::bind(isCloser, _1, _2, std::ref(dists)));
|
||||
const EnemyInfo &ei= *range::min_element(targets.unreachableEnemies, std::bind(isCloser, _1, _2, std::ref(dists)));
|
||||
if(distToNearestNeighbour(ei.s->position, dists) < GameConstants::BFIELD_SIZE)
|
||||
{
|
||||
return goTowards(stack, ei.s->position);
|
||||
@ -179,7 +173,7 @@ BattleAction CBattleAI::activeStack( const CStack * stack )
|
||||
}
|
||||
catch(std::exception &e)
|
||||
{
|
||||
logAi->errorStream() << "Exception occurred in " << __FUNCTION__ << " " << e.what();
|
||||
logAi->error("Exception occurred in %s %s",__FUNCTION__, e.what());
|
||||
}
|
||||
|
||||
return BattleAction::makeDefend(stack);
|
||||
@ -268,7 +262,7 @@ void CBattleAI::battleStacksRemoved(const BattleStacksRemoved & bsr)
|
||||
|
||||
void CBattleAI::print(const std::string &text) const
|
||||
{
|
||||
logAi->traceStream() << "CBattleAI [" << this <<"]: " << text;
|
||||
logAi->trace("CBattleAI [%p]: %s", this, text);
|
||||
}
|
||||
|
||||
BattleAction CBattleAI::goTowards(const CStack * stack, BattleHex destination)
|
||||
@ -283,7 +277,7 @@ BattleAction CBattleAI::goTowards(const CStack * stack, BattleHex destination)
|
||||
auto destNeighbours = destination.neighbouringTiles();
|
||||
if(vstd::contains_if(destNeighbours, [&](BattleHex n) { return stack->coversPos(destination); }))
|
||||
{
|
||||
logAi->warnStream() << "Warning: already standing on neighbouring tile!";
|
||||
logAi->warn("Warning: already standing on neighbouring tile!");
|
||||
//We shouldn't even be here...
|
||||
return BattleAction::makeDefend(stack);
|
||||
}
|
||||
@ -358,6 +352,7 @@ struct PossibleSpellcast
|
||||
{
|
||||
const CSpell *spell;
|
||||
BattleHex dest;
|
||||
si32 value;
|
||||
};
|
||||
|
||||
struct CurrentOffensivePotential
|
||||
@ -430,9 +425,9 @@ void CBattleAI::attemptCastingSpell()
|
||||
std::vector<PossibleSpellcast> possibleCasts;
|
||||
for(auto spell : possibleSpells)
|
||||
{
|
||||
for(auto hex : getTargetsToConsider(spell))
|
||||
for(auto hex : getTargetsToConsider(spell, hero))
|
||||
{
|
||||
PossibleSpellcast ps = {spell, hex};
|
||||
PossibleSpellcast ps = {spell, hex, 0};
|
||||
possibleCasts.push_back(ps);
|
||||
}
|
||||
}
|
||||
@ -457,8 +452,8 @@ void CBattleAI::attemptCastingSpell()
|
||||
case OFFENSIVE_SPELL:
|
||||
{
|
||||
int damageDealt = 0, damageReceived = 0;
|
||||
|
||||
auto stacksSuffering = ps.spell->getAffectedStacks(cb.get(), ECastingMode::HERO_CASTING, playerID, skillLevel, ps.dest, hero);
|
||||
|
||||
auto stacksSuffering = ps.spell->getAffectedStacks(cb.get(), ECastingMode::HERO_CASTING, hero, skillLevel, ps.dest);
|
||||
|
||||
if(stacksSuffering.empty())
|
||||
return -1;
|
||||
@ -472,41 +467,52 @@ void CBattleAI::attemptCastingSpell()
|
||||
damageDealt += dmg;
|
||||
}
|
||||
|
||||
const int damageDiff = damageDealt - damageReceived;
|
||||
const int damageDiff = damageDealt - damageReceived * 10;
|
||||
|
||||
|
||||
LOGFL("Casting %s on hex %d would deal %d damage points among %d stacks.",
|
||||
ps.spell->name % ps.dest % damageDiff % stacksSuffering.size());
|
||||
LOGFL("Casting %s on hex %d would deal { %d %d } damage points among %d stacks.",
|
||||
ps.spell->name % ps.dest % damageDealt % damageReceived % stacksSuffering.size());
|
||||
//TODO tactic effect too
|
||||
return damageDiff;
|
||||
}
|
||||
case TIMED_EFFECT:
|
||||
{
|
||||
StackWithBonuses swb;
|
||||
swb.stack = cb->battleGetStackByPos(ps.dest);
|
||||
if(!swb.stack)
|
||||
auto stacksAffected = ps.spell->getAffectedStacks(cb.get(), ECastingMode::HERO_CASTING, hero, skillLevel, ps.dest);
|
||||
|
||||
if(stacksAffected.empty())
|
||||
return -1;
|
||||
|
||||
Bonus pseudoBonus;
|
||||
pseudoBonus.sid = ps.spell->id;
|
||||
pseudoBonus.val = skillLevel;
|
||||
pseudoBonus.turnsRemain = 1; //TODO
|
||||
CStack::stackEffectToFeature(swb.bonusesToAdd, pseudoBonus);
|
||||
int totalGain = 0;
|
||||
|
||||
HypotheticChangesToBattleState state;
|
||||
state.bonusesOfStacks[swb.stack] = &swb;
|
||||
for(const CStack * sta : stacksAffected)
|
||||
{
|
||||
StackWithBonuses swb;
|
||||
swb.stack = sta;
|
||||
|
||||
PotentialTargets pt(swb.stack, state);
|
||||
auto newValue = pt.bestActionValue();
|
||||
auto oldValue = valueOfStack[swb.stack];
|
||||
auto gain = newValue - oldValue;
|
||||
if(swb.stack->owner != playerID) //enemy
|
||||
gain = -gain;
|
||||
Bonus pseudoBonus;
|
||||
pseudoBonus.sid = ps.spell->id;
|
||||
pseudoBonus.val = skillLevel;
|
||||
pseudoBonus.turnsRemain = 1; //TODO
|
||||
CStack::stackEffectToFeature(swb.bonusesToAdd, pseudoBonus);
|
||||
|
||||
LOGFL("Casting %s on %s would improve the stack by %d points (from %d to %d)",
|
||||
ps.spell->name % swb.stack->nodeName() % gain % (oldValue) % (newValue));
|
||||
HypotheticChangesToBattleState state;
|
||||
state.bonusesOfStacks[swb.stack] = &swb;
|
||||
|
||||
return gain;
|
||||
PotentialTargets pt(swb.stack, state);
|
||||
auto newValue = pt.bestActionValue();
|
||||
auto oldValue = valueOfStack[swb.stack];
|
||||
auto gain = newValue - oldValue;
|
||||
if(swb.stack->owner != playerID) //enemy
|
||||
gain = -gain;
|
||||
|
||||
LOGFL("Casting %s on %s would improve the stack by %d points (from %d to %d)",
|
||||
ps.spell->name % sta->nodeName() % (gain) % (oldValue) % (newValue));
|
||||
|
||||
totalGain += gain;
|
||||
}
|
||||
|
||||
LOGFL("Total gain of cast %s at hex %d is %d", ps.spell->name % (ps.dest.hex) % (totalGain));
|
||||
|
||||
return totalGain;
|
||||
}
|
||||
default:
|
||||
assert(0);
|
||||
@ -514,7 +520,15 @@ void CBattleAI::attemptCastingSpell()
|
||||
}
|
||||
};
|
||||
|
||||
auto castToPerform = *vstd::maxElementByFun(possibleCasts, evaluateSpellcast);
|
||||
for(PossibleSpellcast & psc : possibleCasts)
|
||||
psc.value = evaluateSpellcast(psc);
|
||||
|
||||
auto pscValue = [] (const PossibleSpellcast &ps) -> int
|
||||
{
|
||||
return ps.value;
|
||||
};
|
||||
|
||||
auto castToPerform = *vstd::maxElementByFun(possibleCasts, pscValue);
|
||||
LOGFL("Best spell is %s. Will cast.", castToPerform.spell->name);
|
||||
|
||||
BattleAction spellcast;
|
||||
@ -527,24 +541,60 @@ void CBattleAI::attemptCastingSpell()
|
||||
cb->battleMakeAction(&spellcast);
|
||||
}
|
||||
|
||||
std::vector<BattleHex> CBattleAI::getTargetsToConsider( const CSpell *spell ) const
|
||||
std::vector<BattleHex> CBattleAI::getTargetsToConsider(const CSpell * spell, const ISpellCaster * caster) const
|
||||
{
|
||||
if(spell->getTargetType() == CSpell::NO_TARGET)
|
||||
const CSpell::TargetInfo targetInfo(spell, caster->getSpellSchoolLevel(spell));
|
||||
std::vector<BattleHex> ret;
|
||||
|
||||
if(targetInfo.massive || targetInfo.type == CSpell::NO_TARGET)
|
||||
{
|
||||
//Spell can be casted anywhere, all hexes are potentially considerable.
|
||||
std::vector<BattleHex> ret;
|
||||
|
||||
for(int i = 0; i < GameConstants::BFIELD_SIZE; i++)
|
||||
if(BattleHex(i).isAvailable())
|
||||
ret.push_back(i);
|
||||
|
||||
return ret;
|
||||
ret.push_back(BattleHex());
|
||||
}
|
||||
else
|
||||
{
|
||||
//TODO when massive effect -> doesn't matter where cast
|
||||
return cbc->battleGetPossibleTargets(playerID, spell);
|
||||
switch(targetInfo.type)
|
||||
{
|
||||
case CSpell::CREATURE:
|
||||
{
|
||||
for(const CStack * stack : cbc->battleAliveStacks())
|
||||
{
|
||||
bool immune = ESpellCastProblem::OK != spell->isImmuneByStack(caster, stack);
|
||||
bool casterStack = stack->owner == caster->getOwner();
|
||||
|
||||
if(!immune)
|
||||
switch (spell->positiveness)
|
||||
{
|
||||
case CSpell::POSITIVE:
|
||||
if(casterStack || targetInfo.smart)
|
||||
ret.push_back(stack->position);
|
||||
break;
|
||||
|
||||
case CSpell::NEUTRAL:
|
||||
ret.push_back(stack->position);
|
||||
break;
|
||||
|
||||
case CSpell::NEGATIVE:
|
||||
if(!casterStack || targetInfo.smart)
|
||||
ret.push_back(stack->position);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case CSpell::LOCATION:
|
||||
{
|
||||
for(int i = 0; i < GameConstants::BFIELD_SIZE; i++)
|
||||
if(BattleHex(i).isAvailable())
|
||||
ret.push_back(i);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
boost::optional<BattleAction> CBattleAI::considerFleeingOrSurrendering()
|
||||
@ -610,13 +660,14 @@ ThreatMap::ThreatMap(const CStack *Endangered) : endangered(Endangered)
|
||||
|
||||
const TBonusListPtr StackWithBonuses::getAllBonuses(const CSelector &selector, const CSelector &limit, const CBonusSystemNode *root /*= nullptr*/, const std::string &cachingStr /*= ""*/) const
|
||||
{
|
||||
TBonusListPtr ret = make_shared<BonusList>();
|
||||
TBonusListPtr ret = std::make_shared<BonusList>();
|
||||
const TBonusListPtr originalList = stack->getAllBonuses(selector, limit, root, cachingStr);
|
||||
range::copy(*originalList, std::back_inserter(*ret));
|
||||
for(auto &bonus : bonusesToAdd)
|
||||
{
|
||||
if(selector(&bonus) && (!limit || !limit(&bonus)))
|
||||
ret->push_back(&bonus);
|
||||
auto b = std::make_shared<Bonus>(bonus);
|
||||
if(selector(b.get()) && (!limit || !limit(b.get())))
|
||||
ret->push_back(b);
|
||||
}
|
||||
|
||||
//TODO limiters?
|
||||
@ -643,7 +694,7 @@ AttackPossibility AttackPossibility::evaluate(const BattleAttackInfo &AttackInfo
|
||||
auto attacker = AttackInfo.attacker;
|
||||
auto enemy = AttackInfo.defender;
|
||||
|
||||
const int remainingCounterAttacks = getValOr(state.counterAttacksLeft, enemy, enemy->counterAttacks);
|
||||
const int remainingCounterAttacks = getValOr(state.counterAttacksLeft, enemy, enemy->counterAttacksRemaining());
|
||||
const bool counterAttacksBlocked = attacker->hasBonusOfType(Bonus::BLOCKS_RETALIATION) || enemy->hasBonusOfType(Bonus::NO_RETALIATION);
|
||||
const int totalAttacks = 1 + AttackInfo.attackerBonuses->getBonuses(Selector::type(Bonus::ADDITIONAL_ATTACK), (Selector::effectRange (Bonus::NO_LIMIT).Or(Selector::effectRange(Bonus::ONLY_MELEE_FIGHT))))->totalValue();
|
||||
|
||||
@ -653,7 +704,7 @@ AttackPossibility AttackPossibility::evaluate(const BattleAttackInfo &AttackInfo
|
||||
for(int i = 0; i < totalAttacks; i++)
|
||||
{
|
||||
std::pair<ui32, ui32> retaliation(0,0);
|
||||
auto attackDmg = cbc->battleEstimateDamage(curBai, &retaliation);
|
||||
auto attackDmg = cbc->battleEstimateDamage(CRandomGenerator::getDefault(), curBai, &retaliation);
|
||||
ap.damageDealt = (attackDmg.first + attackDmg.second) / 2;
|
||||
ap.damageReceived = (retaliation.first + retaliation.second) / 2;
|
||||
|
||||
@ -737,7 +788,7 @@ int PotentialTargets::bestActionValue() const
|
||||
|
||||
void EnemyInfo::calcDmg(const CStack * ourStack)
|
||||
{
|
||||
TDmgRange retal, dmg = cbc->battleEstimateDamage(ourStack, s, &retal);
|
||||
TDmgRange retal, dmg = cbc->battleEstimateDamage(CRandomGenerator::getDefault(), ourStack, s, &retal);
|
||||
adi = (dmg.first + dmg.second) / 2;
|
||||
adr = (retal.first + retal.second) / 2;
|
||||
}
|
||||
|
@ -51,11 +51,11 @@ static bool willSecondHexBlockMoreEnemyShooters(const BattleHex &h1, const Battl
|
||||
|
||||
|
||||
struct ThreatMap
|
||||
{
|
||||
{
|
||||
std::array<std::vector<BattleAttackInfo>, GameConstants::BFIELD_SIZE> threatMap; // [hexNr] -> enemies able to strike
|
||||
|
||||
const CStack *endangered;
|
||||
std::array<int, GameConstants::BFIELD_SIZE> sufferedDamage;
|
||||
|
||||
const CStack *endangered;
|
||||
std::array<int, GameConstants::BFIELD_SIZE> sufferedDamage;
|
||||
|
||||
ThreatMap(const CStack *Endangered);
|
||||
};
|
||||
@ -89,7 +89,7 @@ const Val getValOr(const std::map<Key, Val> &Map, const Key &key, const Val2 def
|
||||
auto i = Map.find(key);
|
||||
if(i != Map.end())
|
||||
return i->second;
|
||||
else
|
||||
else
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
@ -110,9 +110,9 @@ struct PotentialTargets
|
||||
class CBattleAI : public CBattleGameInterface
|
||||
{
|
||||
int side;
|
||||
shared_ptr<CBattleCallback> cb;
|
||||
|
||||
//Previous setting of cb
|
||||
std::shared_ptr<CBattleCallback> cb;
|
||||
|
||||
//Previous setting of cb
|
||||
bool wasWaitingForRealize, wasUnlockingGs;
|
||||
|
||||
void print(const std::string &text) const;
|
||||
@ -120,7 +120,7 @@ public:
|
||||
CBattleAI(void);
|
||||
~CBattleAI(void);
|
||||
|
||||
void init(shared_ptr<CBattleCallback> CB) override;
|
||||
void init(std::shared_ptr<CBattleCallback> CB) override;
|
||||
void actionFinished(const BattleAction &action) override;//occurs AFTER every action taken by any stack or by the hero
|
||||
void actionStarted(const BattleAction &action) override;//occurs BEFORE every action taken by any stack or by the hero
|
||||
BattleAction activeStack(const CStack * stack) override; //called when it's turn of that stack
|
||||
@ -148,6 +148,6 @@ public:
|
||||
boost::optional<BattleAction> considerFleeingOrSurrendering();
|
||||
|
||||
void attemptCastingSpell();
|
||||
std::vector<BattleHex> getTargetsToConsider(const CSpell *spell) const;
|
||||
std::vector<BattleHex> getTargetsToConsider(const CSpell *spell, const ISpellCaster * caster) const;
|
||||
};
|
||||
|
||||
|
@ -1,12 +1,12 @@
|
||||
project(battleAI)
|
||||
cmake_minimum_required(VERSION 2.6)
|
||||
|
||||
include_directories(${Boost_INCLUDE_DIRS} ${CMAKE_HOME_DIRECTORY} ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_HOME_DIRECTORY}/lib)
|
||||
include_directories(${Boost_INCLUDE_DIRS} ${CMAKE_HOME_DIRECTORY} ${CMAKE_HOME_DIRECTORY}/include ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_HOME_DIRECTORY}/lib)
|
||||
|
||||
set(battleAI_SRCS
|
||||
StdInc.cpp
|
||||
BattleAI.cpp
|
||||
main.cpp
|
||||
BattleAI.cpp
|
||||
main.cpp
|
||||
)
|
||||
|
||||
add_library(BattleAI SHARED ${battleAI_SRCS})
|
||||
|
@ -1,2 +1,2 @@
|
||||
// Creates the precompiled header
|
||||
#include "StdInc.h"
|
||||
#include "StdInc.h"
|
||||
|
@ -25,7 +25,7 @@ extern "C" DLL_EXPORT void GetAiName(char* name)
|
||||
strcpy_s(name, strlen(g_cszAiName) + 1, g_cszAiName);
|
||||
}
|
||||
|
||||
extern "C" DLL_EXPORT void GetNewBattleAI(shared_ptr<CBattleGameInterface> &out)
|
||||
extern "C" DLL_EXPORT void GetNewBattleAI(std::shared_ptr<CBattleGameInterface> &out)
|
||||
{
|
||||
out = make_shared<CBattleAI>();
|
||||
out = std::make_shared<CBattleAI>();
|
||||
}
|
||||
|
@ -1,9 +1,15 @@
|
||||
project(AI)
|
||||
cmake_minimum_required(VERSION 2.8)
|
||||
|
||||
find_package(Fuzzylite)
|
||||
option(FORCE_BUNDLED_FL "Force to use FuzzyLite included into VCMI's source tree" OFF)
|
||||
|
||||
if(NOT MSVC)
|
||||
if (NOT FORCE_BUNDLED_FL)
|
||||
find_package(Fuzzylite)
|
||||
else()
|
||||
set(FL_FOUND FALSE)
|
||||
endif()
|
||||
|
||||
if (NOT MSVC)
|
||||
add_definitions(-DFL_CPP11)
|
||||
set(FL_CPP11 ON CACHE BOOL "")
|
||||
endif()
|
||||
@ -16,4 +22,4 @@ endif()
|
||||
add_subdirectory(BattleAI)
|
||||
add_subdirectory(StupidAI)
|
||||
add_subdirectory(EmptyAI)
|
||||
add_subdirectory(VCAI)
|
||||
add_subdirectory(VCAI)
|
||||
|
@ -3,12 +3,11 @@
|
||||
|
||||
#include "../../lib/CRandomGenerator.h"
|
||||
|
||||
void CEmptyAI::init(shared_ptr<CCallback> CB)
|
||||
void CEmptyAI::init(std::shared_ptr<CCallback> CB)
|
||||
{
|
||||
cb = CB;
|
||||
human=false;
|
||||
playerID = *cb->getMyColor();
|
||||
//logAi->infoStream() << "EmptyAI initialized.";
|
||||
}
|
||||
void CEmptyAI::yourTurn()
|
||||
{
|
||||
@ -30,7 +29,7 @@ void CEmptyAI::showBlockingDialog(const std::string &text, const std::vector<Com
|
||||
cb->selectionMade(0, askID);
|
||||
}
|
||||
|
||||
void CEmptyAI::showTeleportDialog(TeleportChannelID channel, std::vector<ObjectInstanceID> exits, bool impassable, QueryID askID)
|
||||
void CEmptyAI::showTeleportDialog(TeleportChannelID channel, TTeleportExitsList exits, bool impassable, QueryID askID)
|
||||
{
|
||||
cb->selectionMade(0, askID);
|
||||
}
|
||||
|
@ -7,15 +7,15 @@ struct HeroMoveDetails;
|
||||
|
||||
class CEmptyAI : public CGlobalAI
|
||||
{
|
||||
shared_ptr<CCallback> cb;
|
||||
std::shared_ptr<CCallback> cb;
|
||||
|
||||
public:
|
||||
void init(shared_ptr<CCallback> CB) override;
|
||||
void init(std::shared_ptr<CCallback> CB) override;
|
||||
void yourTurn() override;
|
||||
void heroGotLevel(const CGHeroInstance *hero, PrimarySkill::PrimarySkill pskill, std::vector<SecondarySkill> &skills, QueryID queryID) override;
|
||||
void commanderGotLevel (const CCommanderInstance * commander, std::vector<ui32> skills, QueryID queryID) override;
|
||||
void showBlockingDialog(const std::string &text, const std::vector<Component> &components, QueryID askID, const int soundID, bool selection, bool cancel) override;
|
||||
void showTeleportDialog(TeleportChannelID channel, std::vector<ObjectInstanceID> exits, bool impassable, QueryID askID) override;
|
||||
void showTeleportDialog(TeleportChannelID channel, TTeleportExitsList exits, bool impassable, QueryID askID) override;
|
||||
void showGarrisonDialog(const CArmedInstance *up, const CGHeroInstance *down, bool removableUnits, QueryID queryID) override;
|
||||
};
|
||||
|
||||
|
@ -1,11 +1,11 @@
|
||||
project(emptyAI)
|
||||
cmake_minimum_required(VERSION 2.6)
|
||||
|
||||
include_directories(${Boost_INCLUDE_DIRS} ${CMAKE_HOME_DIRECTORY} ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_HOME_DIRECTORY}/lib)
|
||||
include_directories(${Boost_INCLUDE_DIRS} ${CMAKE_HOME_DIRECTORY} ${CMAKE_HOME_DIRECTORY}/include ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_HOME_DIRECTORY}/lib)
|
||||
|
||||
set(emptyAI_SRCS
|
||||
CEmptyAI.cpp
|
||||
exp_funcs.cpp
|
||||
CEmptyAI.cpp
|
||||
exp_funcs.cpp
|
||||
)
|
||||
|
||||
add_library(EmptyAI SHARED ${emptyAI_SRCS})
|
||||
|
@ -6,58 +6,50 @@
|
||||
<Option pch_mode="2" />
|
||||
<Option compiler="gcc" />
|
||||
<Build>
|
||||
<Target title="Debug-win32-SDL2">
|
||||
<Target title="Debug-win32">
|
||||
<Option platforms="Windows;" />
|
||||
<Option output="../EmptyAI" imp_lib="$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).a" def_file="$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).def" prefix_auto="1" extension_auto="1" />
|
||||
<Option object_output="obj/Debug/" />
|
||||
<Option object_output="obj/Debug/x86/" />
|
||||
<Option type="3" />
|
||||
<Option compiler="gcc" />
|
||||
<Compiler>
|
||||
<Add option="-ggdb" />
|
||||
</Compiler>
|
||||
</Target>
|
||||
<Target title="Release-win32-SDL2">
|
||||
<Option platforms="Windows;" />
|
||||
<Option output="../EmptyAI" imp_lib="$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).a" def_file="$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).def" prefix_auto="1" extension_auto="1" />
|
||||
<Option object_output="obj/Release/" />
|
||||
<Option type="3" />
|
||||
<Option compiler="gcc" />
|
||||
<Compiler>
|
||||
<Add option="-fomit-frame-pointer" />
|
||||
<Add option="-O3" />
|
||||
</Compiler>
|
||||
<Linker>
|
||||
<Add option="-s" />
|
||||
<Add directory="$(#boost.lib32)" />
|
||||
</Linker>
|
||||
</Target>
|
||||
<Target title="Debug-win32-SDL1">
|
||||
<Target title="Release-win32">
|
||||
<Option platforms="Windows;" />
|
||||
<Option output="../EmptyAI" imp_lib="$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).a" def_file="$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).def" prefix_auto="1" extension_auto="1" />
|
||||
<Option object_output="obj/Debug/" />
|
||||
<Option object_output="obj/Release/x86/" />
|
||||
<Option type="3" />
|
||||
<Option compiler="gcc" />
|
||||
<Compiler>
|
||||
<Add option="-O2" />
|
||||
</Compiler>
|
||||
<Linker>
|
||||
<Add directory="$(#boost.lib32)" />
|
||||
</Linker>
|
||||
</Target>
|
||||
<Target title="Debug-win64">
|
||||
<Option platforms="Windows;" />
|
||||
<Option output="../EmptyAI" imp_lib="$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).a" def_file="$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).def" prefix_auto="1" extension_auto="1" />
|
||||
<Option object_output="obj/Debug/x64/" />
|
||||
<Option type="3" />
|
||||
<Option compiler="gnu_gcc_compiler_x64" />
|
||||
<Compiler>
|
||||
<Add option="-ggdb" />
|
||||
</Compiler>
|
||||
</Target>
|
||||
<Target title="Release-win32-SDL1">
|
||||
<Option platforms="Windows;" />
|
||||
<Option output="../EmptyAI" imp_lib="$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).a" def_file="$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).def" prefix_auto="1" extension_auto="1" />
|
||||
<Option object_output="obj/Release/" />
|
||||
<Option type="3" />
|
||||
<Option compiler="gcc" />
|
||||
<Compiler>
|
||||
<Add option="-fomit-frame-pointer" />
|
||||
<Add option="-O3" />
|
||||
</Compiler>
|
||||
<Linker>
|
||||
<Add option="-s" />
|
||||
<Add directory="$(#boost.lib64)" />
|
||||
</Linker>
|
||||
</Target>
|
||||
</Build>
|
||||
<Compiler>
|
||||
<Add option="-Wextra" />
|
||||
<Add option="-Wall" />
|
||||
<Add option="-std=gnu++11" />
|
||||
<Add option="-fexceptions" />
|
||||
<Add option="-Wpointer-arith" />
|
||||
<Add option="-Wno-switch" />
|
||||
@ -71,12 +63,12 @@
|
||||
<Linker>
|
||||
<Add option="-lboost_system$(#boost.libsuffix)" />
|
||||
<Add option="-lVCMI_lib" />
|
||||
<Add directory="$(#boost.lib32)" />
|
||||
<Add directory="../.." />
|
||||
</Linker>
|
||||
<Unit filename="CEmptyAI.cpp" />
|
||||
<Unit filename="CEmptyAI.h" />
|
||||
<Unit filename="StdInc.h">
|
||||
<Option compile="1" />
|
||||
<Option weight="0" />
|
||||
</Unit>
|
||||
<Unit filename="exp_funcs.cpp" />
|
||||
|
@ -1,2 +1,2 @@
|
||||
// Creates the precompiled header
|
||||
#include "StdInc.h"
|
||||
#include "StdInc.h"
|
||||
|
@ -13,7 +13,7 @@ extern "C" DLL_EXPORT void GetAiName(char* name)
|
||||
strcpy(name,NAME);
|
||||
}
|
||||
|
||||
extern "C" DLL_EXPORT void GetNewAI(shared_ptr<CGlobalAI> &out)
|
||||
extern "C" DLL_EXPORT void GetNewAI(std::shared_ptr<CGlobalAI> &out)
|
||||
{
|
||||
out = make_shared<CEmptyAI>();
|
||||
}
|
||||
out = std::make_shared<CEmptyAI>();
|
||||
}
|
||||
|
@ -6,23 +6,24 @@
|
||||
<Option pch_mode="2" />
|
||||
<Option compiler="gcc" />
|
||||
<Build>
|
||||
<Target title="Debug-win32-SDL2">
|
||||
<Target title="Debug-win32">
|
||||
<Option platforms="Windows;" />
|
||||
<Option output="bin/Debug/FuzzyLite" prefix_auto="1" extension_auto="1" />
|
||||
<Option output="../FuzzyLite" prefix_auto="1" extension_auto="1" />
|
||||
<Option working_dir="" />
|
||||
<Option object_output="obj/Debug/" />
|
||||
<Option object_output="obj/Debug/x86/" />
|
||||
<Option type="2" />
|
||||
<Option compiler="gcc" />
|
||||
<Option createDefFile="1" />
|
||||
<Compiler>
|
||||
<Add option="-Og" />
|
||||
<Add option="-g" />
|
||||
</Compiler>
|
||||
</Target>
|
||||
<Target title="Release-win32-SDL2">
|
||||
<Target title="Release-win32">
|
||||
<Option platforms="Windows;" />
|
||||
<Option output="bin/Release/FuzzyLite" prefix_auto="1" extension_auto="1" />
|
||||
<Option output="../FuzzyLite" prefix_auto="1" extension_auto="1" />
|
||||
<Option working_dir="" />
|
||||
<Option object_output="obj/Release/" />
|
||||
<Option object_output="obj/Release/x86/" />
|
||||
<Option type="2" />
|
||||
<Option compiler="gcc" />
|
||||
<Option createDefFile="1" />
|
||||
@ -34,38 +35,24 @@
|
||||
<Add option="-s" />
|
||||
</Linker>
|
||||
</Target>
|
||||
<Target title="Debug-win32-SDL1">
|
||||
<Target title="Debug-win64">
|
||||
<Option platforms="Windows;" />
|
||||
<Option output="bin/Debug/FuzzyLite" prefix_auto="1" extension_auto="1" />
|
||||
<Option output="../FuzzyLite" prefix_auto="1" extension_auto="1" />
|
||||
<Option working_dir="" />
|
||||
<Option object_output="obj/Debug/" />
|
||||
<Option object_output="obj/Debug/x64/" />
|
||||
<Option type="2" />
|
||||
<Option compiler="gcc" />
|
||||
<Option compiler="gnu_gcc_compiler_x64" />
|
||||
<Option createDefFile="1" />
|
||||
<Compiler>
|
||||
<Add option="-Og" />
|
||||
<Add option="-g" />
|
||||
</Compiler>
|
||||
</Target>
|
||||
<Target title="Release-win32-SDL1">
|
||||
<Option platforms="Windows;" />
|
||||
<Option output="bin/Release/FuzzyLite" prefix_auto="1" extension_auto="1" />
|
||||
<Option working_dir="" />
|
||||
<Option object_output="obj/Release/" />
|
||||
<Option type="2" />
|
||||
<Option compiler="gcc" />
|
||||
<Option createDefFile="1" />
|
||||
<Compiler>
|
||||
<Add option="-fomit-frame-pointer" />
|
||||
<Add option="-O2" />
|
||||
</Compiler>
|
||||
<Linker>
|
||||
<Add option="-s" />
|
||||
</Linker>
|
||||
</Target>
|
||||
</Build>
|
||||
<Compiler>
|
||||
<Add option="-Wextra" />
|
||||
<Add option="-Wall" />
|
||||
<Add option="-std=gnu++11" />
|
||||
<Add option="-fexceptions" />
|
||||
<Add option="-Wpointer-arith" />
|
||||
<Add option="-Wno-switch" />
|
||||
@ -74,7 +61,6 @@
|
||||
<Add option="-Wno-overloaded-virtual" />
|
||||
<Add option="-DFL_CPP11" />
|
||||
<Add option="-DFL_WINDOWS" />
|
||||
<Add directory="$(#boost.include)" />
|
||||
<Add directory="fuzzylite" />
|
||||
</Compiler>
|
||||
<Unit filename="fuzzylite/fl/Console.h" />
|
||||
|
@ -251,7 +251,7 @@
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='RD|Win32'">
|
||||
<OutDir>..</OutDir>
|
||||
<IncludePath>$(IncludePath)</IncludePath>
|
||||
<IncludePath>$(SolutionDir)\AI\FuzzyLite\fuzzylite;$(IncludePath)</IncludePath>
|
||||
<LibraryPath>$(LibraryPath)</LibraryPath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='RD|x64'">
|
||||
|
@ -1,12 +1,12 @@
|
||||
project(stupidAI)
|
||||
cmake_minimum_required(VERSION 2.6)
|
||||
|
||||
include_directories(${Boost_INCLUDE_DIRS} ${CMAKE_HOME_DIRECTORY} ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_HOME_DIRECTORY}/lib)
|
||||
include_directories(${Boost_INCLUDE_DIRS} ${CMAKE_HOME_DIRECTORY} ${CMAKE_HOME_DIRECTORY}/include ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_HOME_DIRECTORY}/lib)
|
||||
|
||||
set(stupidAI_SRCS
|
||||
StdInc.cpp
|
||||
StupidAI.cpp
|
||||
main.cpp
|
||||
StupidAI.cpp
|
||||
main.cpp
|
||||
)
|
||||
|
||||
add_library(StupidAI SHARED ${stupidAI_SRCS})
|
||||
|
@ -1,2 +1,2 @@
|
||||
// Creates the precompiled header
|
||||
#include "StdInc.h"
|
||||
#include "StdInc.h"
|
||||
|
@ -6,44 +6,20 @@
|
||||
<Option pch_mode="2" />
|
||||
<Option compiler="gcc" />
|
||||
<Build>
|
||||
<Target title="Debug-win32-SDL2">
|
||||
<Target title="Debug-win32">
|
||||
<Option platforms="Windows;" />
|
||||
<Option output="../StupidAI" imp_lib="$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).a" def_file="$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).def" prefix_auto="1" extension_auto="1" />
|
||||
<Option object_output="obj/Debug/" />
|
||||
<Option object_output="obj/Debug/x86" />
|
||||
<Option type="3" />
|
||||
<Option compiler="gcc" />
|
||||
<Compiler>
|
||||
<Add option="-ggdb" />
|
||||
</Compiler>
|
||||
</Target>
|
||||
<Target title="Release-win32-SDL2">
|
||||
<Target title="Release-win32">
|
||||
<Option platforms="Windows;" />
|
||||
<Option output="../StupidAI" imp_lib="$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).a" def_file="$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).def" prefix_auto="1" extension_auto="1" />
|
||||
<Option object_output="obj/Release/" />
|
||||
<Option type="3" />
|
||||
<Option compiler="gcc" />
|
||||
<Compiler>
|
||||
<Add option="-fomit-frame-pointer" />
|
||||
<Add option="-O3" />
|
||||
</Compiler>
|
||||
<Linker>
|
||||
<Add option="-s" />
|
||||
</Linker>
|
||||
</Target>
|
||||
<Target title="Debug-win32-SDL1">
|
||||
<Option platforms="Windows;" />
|
||||
<Option output="../StupidAI" imp_lib="$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).a" def_file="$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).def" prefix_auto="1" extension_auto="1" />
|
||||
<Option object_output="obj/Debug/" />
|
||||
<Option type="3" />
|
||||
<Option compiler="gcc" />
|
||||
<Compiler>
|
||||
<Add option="-ggdb" />
|
||||
</Compiler>
|
||||
</Target>
|
||||
<Target title="Release-win32-SDL1">
|
||||
<Option platforms="Windows;" />
|
||||
<Option output="../StupidAI" imp_lib="$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).a" def_file="$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).def" prefix_auto="1" extension_auto="1" />
|
||||
<Option object_output="obj/Release/" />
|
||||
<Option object_output="obj/Release/x86" />
|
||||
<Option type="3" />
|
||||
<Option compiler="gcc" />
|
||||
<Compiler>
|
||||
@ -59,6 +35,7 @@
|
||||
<Add option="-pedantic" />
|
||||
<Add option="-Wextra" />
|
||||
<Add option="-Wall" />
|
||||
<Add option="-std=gnu++11" />
|
||||
<Add option="-fexceptions" />
|
||||
<Add option="-Wpointer-arith" />
|
||||
<Add option="-Wno-switch" />
|
||||
@ -77,6 +54,7 @@
|
||||
<Add directory="../.." />
|
||||
</Linker>
|
||||
<Unit filename="StdInc.h">
|
||||
<Option compile="1" />
|
||||
<Option weight="0" />
|
||||
</Unit>
|
||||
<Unit filename="StupidAI.cpp" />
|
||||
|
@ -5,7 +5,7 @@
|
||||
#include "../../CCallback.h"
|
||||
#include "../../lib/CCreatureHandler.h"
|
||||
|
||||
static shared_ptr<CBattleCallback> cbc;
|
||||
static std::shared_ptr<CBattleCallback> cbc;
|
||||
|
||||
CStupidAI::CStupidAI(void)
|
||||
: side(-1)
|
||||
@ -19,7 +19,7 @@ CStupidAI::~CStupidAI(void)
|
||||
print("destroyed");
|
||||
}
|
||||
|
||||
void CStupidAI::init(shared_ptr<CBattleCallback> CB)
|
||||
void CStupidAI::init(std::shared_ptr<CBattleCallback> CB)
|
||||
{
|
||||
print("init called, saving ptr to IBattleCallback");
|
||||
cbc = cb = CB;
|
||||
@ -44,7 +44,7 @@ struct EnemyInfo
|
||||
{}
|
||||
void calcDmg(const CStack * ourStack)
|
||||
{
|
||||
TDmgRange retal, dmg = cbc->battleEstimateDamage(ourStack, s, &retal);
|
||||
TDmgRange retal, dmg = cbc->battleEstimateDamage(CRandomGenerator::getDefault(), ourStack, s, &retal);
|
||||
adi = (dmg.first + dmg.second) / 2;
|
||||
adr = (retal.first + retal.second) / 2;
|
||||
}
|
||||
@ -108,7 +108,7 @@ BattleAction CStupidAI::activeStack( const CStack * stack )
|
||||
if(stack->type->idNumber == CreatureID::CATAPULT)
|
||||
{
|
||||
BattleAction attack;
|
||||
static const std::vector<int> wallHexes = {50, 183, 182, 130, 62, 29, 12, 95};
|
||||
static const std::vector<int> wallHexes = {50, 183, 182, 130, 78, 29, 12, 95};
|
||||
|
||||
attack.destinationTile = *RandomGeneratorUtil::nextItem(wallHexes, CRandomGenerator::getDefault());
|
||||
attack.actionType = Battle::CATAPULT;
|
||||
@ -153,6 +153,12 @@ BattleAction CStupidAI::activeStack( const CStack * stack )
|
||||
}
|
||||
}
|
||||
|
||||
for ( auto & enemy : enemiesReachable )
|
||||
enemy.calcDmg( stack );
|
||||
|
||||
for ( auto & enemy : enemiesShootable )
|
||||
enemy.calcDmg( stack );
|
||||
|
||||
if(enemiesShootable.size())
|
||||
{
|
||||
const EnemyInfo &ei= *std::max_element(enemiesShootable.begin(), enemiesShootable.end(), isMoreProfitable);
|
||||
@ -255,7 +261,7 @@ void CStupidAI::battleStacksRemoved(const BattleStacksRemoved & bsr)
|
||||
|
||||
void CStupidAI::print(const std::string &text) const
|
||||
{
|
||||
logAi->traceStream() << "CStupidAI [" << this <<"]: " << text;
|
||||
logAi->trace("CStupidAI [%p]: %s", this, text);
|
||||
}
|
||||
|
||||
BattleAction CStupidAI::goTowards(const CStack * stack, BattleHex destination)
|
||||
@ -270,7 +276,7 @@ BattleAction CStupidAI::goTowards(const CStack * stack, BattleHex destination)
|
||||
auto destNeighbours = destination.neighbouringTiles();
|
||||
if(vstd::contains_if(destNeighbours, [&](BattleHex n) { return stack->coversPos(destination); }))
|
||||
{
|
||||
logAi->warnStream() << "Warning: already standing on neighbouring tile!";
|
||||
logAi->warn("Warning: already standing on neighbouring tile!");
|
||||
//We shouldn't even be here...
|
||||
return BattleAction::makeDefend(stack);
|
||||
}
|
||||
@ -321,13 +327,13 @@ BattleAction CStupidAI::goTowards(const CStack * stack, BattleHex destination)
|
||||
}
|
||||
}
|
||||
|
||||
void CStupidAI::saveGame(COSer & h, const int version)
|
||||
void CStupidAI::saveGame(BinarySerializer & h, const int version)
|
||||
{
|
||||
//TODO to be implemented with saving/loading during the battles
|
||||
assert(0);
|
||||
}
|
||||
|
||||
void CStupidAI::loadGame(CISer & h, const int version)
|
||||
void CStupidAI::loadGame(BinaryDeserializer & h, const int version)
|
||||
{
|
||||
//TODO to be implemented with saving/loading during the battles
|
||||
assert(0);
|
||||
|
@ -5,14 +5,14 @@
|
||||
class CStupidAI : public CBattleGameInterface
|
||||
{
|
||||
int side;
|
||||
shared_ptr<CBattleCallback> cb;
|
||||
std::shared_ptr<CBattleCallback> cb;
|
||||
|
||||
void print(const std::string &text) const;
|
||||
public:
|
||||
CStupidAI(void);
|
||||
~CStupidAI(void);
|
||||
|
||||
void init(shared_ptr<CBattleCallback> CB) override;
|
||||
void init(std::shared_ptr<CBattleCallback> CB) override;
|
||||
void actionFinished(const BattleAction &action) override;//occurs AFTER every action taken by any stack or by the hero
|
||||
void actionStarted(const BattleAction &action) override;//occurs BEFORE every action taken by any stack or by the hero
|
||||
BattleAction activeStack(const CStack * stack) override; //called when it's turn of that stack
|
||||
@ -36,8 +36,8 @@ public:
|
||||
|
||||
BattleAction goTowards(const CStack * stack, BattleHex hex );
|
||||
|
||||
virtual void saveGame(COSer & h, const int version) override;
|
||||
virtual void loadGame(CISer & h, const int version) override;
|
||||
virtual void saveGame(BinarySerializer & h, const int version) override;
|
||||
virtual void loadGame(BinaryDeserializer & h, const int version) override;
|
||||
|
||||
};
|
||||
|
||||
|
@ -25,7 +25,7 @@ extern "C" DLL_EXPORT void GetAiName(char* name)
|
||||
strcpy_s(name, strlen(g_cszAiName) + 1, g_cszAiName);
|
||||
}
|
||||
|
||||
extern "C" DLL_EXPORT void GetNewBattleAI(shared_ptr<CBattleGameInterface> &out)
|
||||
extern "C" DLL_EXPORT void GetNewBattleAI(std::shared_ptr<CBattleGameInterface> &out)
|
||||
{
|
||||
out = make_shared<CStupidAI>();
|
||||
out = std::make_shared<CStupidAI>();
|
||||
}
|
||||
|
@ -7,6 +7,10 @@
|
||||
#include "../../lib/CConfigHandler.h"
|
||||
#include "../../lib/CHeroHandler.h"
|
||||
#include "../../lib/mapObjects/CBank.h"
|
||||
#include "../../lib/mapObjects/CGTownInstance.h"
|
||||
#include "../../lib/mapObjects/CQuest.h"
|
||||
#include "../../lib/CPathfinder.h"
|
||||
#include "../../lib/mapping/CMapDefines.h"
|
||||
|
||||
/*
|
||||
* AIUtility.cpp, part of VCMI engine
|
||||
@ -150,7 +154,7 @@ void foreach_neighbour(const int3 &pos, std::function<void(const int3& pos)> foo
|
||||
{
|
||||
CCallback * cbp = cb.get(); // avoid costly retrieval of thread-specific pointer
|
||||
|
||||
for(const int3 &dir : dirs)
|
||||
for(const int3 &dir : int3::getDirs())
|
||||
{
|
||||
const int3 n = pos + dir;
|
||||
if(cbp->isInTheMap(n))
|
||||
@ -160,7 +164,7 @@ void foreach_neighbour(const int3 &pos, std::function<void(const int3& pos)> foo
|
||||
|
||||
void foreach_neighbour(CCallback * cbp, const int3 &pos, std::function<void(CCallback * cbp, const int3& pos)> foo)
|
||||
{
|
||||
for(const int3 &dir : dirs)
|
||||
for(const int3 &dir : int3::getDirs())
|
||||
{
|
||||
const int3 n = pos + dir;
|
||||
if(cbp->isInTheMap(n))
|
||||
@ -335,7 +339,7 @@ bool isSafeToVisit(HeroPtr h, crint3 tile)
|
||||
{
|
||||
if(heroStrength / SAFE_ATTACK_CONSTANT > dangerStrength)
|
||||
{
|
||||
logAi->traceStream() << boost::format("It's safe for %s to visit tile %s") % h->name % tile;
|
||||
logAi->trace("It's safe for %s to visit tile %s", h->name, tile());
|
||||
return true;
|
||||
}
|
||||
else
|
||||
@ -356,10 +360,10 @@ bool canBeEmbarkmentPoint(const TerrainTile *t, bool fromWater)
|
||||
int3 whereToExplore(HeroPtr h)
|
||||
{
|
||||
TimeCheck tc ("where to explore");
|
||||
int radius = h->getSightRadious();
|
||||
int radius = h->getSightRadius();
|
||||
int3 hpos = h->visitablePos();
|
||||
|
||||
SectorMap sm(h);
|
||||
auto sm = ai->getCachedSectorMap(h);
|
||||
|
||||
//look for nearby objs -> visit them if they're close enouh
|
||||
const int DIST_LIMIT = 3;
|
||||
@ -372,9 +376,9 @@ int3 whereToExplore(HeroPtr h)
|
||||
{
|
||||
int3 op = obj->visitablePos();
|
||||
CGPath p;
|
||||
ai->myCb->getPathsInfo(h.get())->getPath(op, p);
|
||||
ai->myCb->getPathsInfo(h.get())->getPath(p, op);
|
||||
if (p.nodes.size() && p.endPos() == op && p.nodes.size() <= DIST_LIMIT)
|
||||
if (ai->isGoodForVisit(obj, h, sm))
|
||||
if (ai->isGoodForVisit(obj, h, *sm))
|
||||
nearbyVisitableObjs.push_back(obj);
|
||||
}
|
||||
}
|
||||
@ -432,7 +436,7 @@ bool boundaryBetweenTwoPoints (int3 pos1, int3 pos2, CCallback * cbp) //determin
|
||||
for (int y = yMin; y <= yMax; ++y)
|
||||
{
|
||||
int3 tile = int3(x, y, pos1.z); //use only on same level, ofc
|
||||
if (abs(pos1.dist2d(tile) - pos2.dist2d(tile)) < 1.5)
|
||||
if (std::abs(pos1.dist2d(tile) - pos2.dist2d(tile)) < 1.5)
|
||||
{
|
||||
if (!(cbp->isVisible(tile) && cbp->getTile(tile)->blocked)) //if there's invisible or unblocked tile between, it's good
|
||||
return false;
|
||||
@ -505,8 +509,10 @@ bool compareArtifacts(const CArtifactInstance *a1, const CArtifactInstance *a2)
|
||||
auto art1 = a1->artType;
|
||||
auto art2 = a2->artType;
|
||||
|
||||
if (art1->valOfBonuses(Bonus::PRIMARY_SKILL) > art2->valOfBonuses(Bonus::PRIMARY_SKILL))
|
||||
if(art1->price == art2->price)
|
||||
return art1->valOfBonuses(Bonus::PRIMARY_SKILL) > art2->valOfBonuses(Bonus::PRIMARY_SKILL);
|
||||
else if(art1->price > art2->price)
|
||||
return true;
|
||||
else
|
||||
return art1->price > art2->price;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -5,11 +5,9 @@
|
||||
#include "../../lib/CCreatureHandler.h"
|
||||
#include "../../lib/CTownHandler.h"
|
||||
#include "../../lib/spells/CSpellHandler.h"
|
||||
#include "../../lib/Connection.h"
|
||||
#include "../../lib/CGameState.h"
|
||||
#include "../../lib/mapping/CMap.h"
|
||||
#include "../../lib/NetPacks.h"
|
||||
#include "../../lib/CStopWatch.h"
|
||||
#include "../../lib/mapObjects/CObjectHandler.h"
|
||||
#include "../../lib/mapObjects/CGHeroInstance.h"
|
||||
|
||||
/*
|
||||
* AIUtility.h, part of VCMI engine
|
||||
@ -21,10 +19,11 @@
|
||||
*
|
||||
*/
|
||||
|
||||
class CCallback;
|
||||
|
||||
typedef const int3& crint3;
|
||||
typedef const std::string& crstring;
|
||||
|
||||
const int HERO_GOLD_COST = 2500;
|
||||
const int GOLD_MINE_PRODUCTION = 1000, WOOD_ORE_MINE_PRODUCTION = 2, RESOURCE_MINE_PRODUCTION = 1;
|
||||
const int ACTUAL_RESOURCE_COUNT = 7;
|
||||
const int ALLOWED_ROAMING_HEROES = 8;
|
||||
@ -44,7 +43,7 @@ struct HeroPtr
|
||||
public:
|
||||
std::string name;
|
||||
|
||||
|
||||
|
||||
HeroPtr();
|
||||
HeroPtr(const CGHeroInstance *H);
|
||||
~HeroPtr();
|
||||
@ -107,7 +106,7 @@ struct TimeCheck
|
||||
|
||||
~TimeCheck()
|
||||
{
|
||||
logAi->traceStream() << boost::format("Time of %s was %d ms.") % txt % time.getDiff();
|
||||
logAi->trace("Time of %s was %d ms.",txt,time.getDiff());
|
||||
}
|
||||
};
|
||||
|
||||
@ -131,10 +130,10 @@ private:
|
||||
template<int id>
|
||||
bool objWithID(const CGObjectInstance *obj)
|
||||
{
|
||||
return obj->ID == id;
|
||||
return obj->ID == id;
|
||||
}
|
||||
|
||||
std::string strFromInt3(int3 pos);
|
||||
std::string strFromInt3(int3 pos);//todo: remove
|
||||
void foreach_tile_pos(std::function<void(const int3& pos)> foo);
|
||||
void foreach_tile_pos(CCallback * cbp, std::function<void(CCallback * cbp, const int3& pos)> foo); // avoid costly retrieval of thread-specific pointer
|
||||
void foreach_neighbour(const int3 &pos, std::function<void(const int3& pos)> foo);
|
||||
|
@ -2,18 +2,19 @@ project(VCAI)
|
||||
cmake_minimum_required(VERSION 2.6)
|
||||
|
||||
if (FL_FOUND)
|
||||
include_directories(${Boost_INCLUDE_DIRS} ${CMAKE_HOME_DIRECTORY} ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_HOME_DIRECTORY}/lib ${FL_INCLUDE_DIRS})
|
||||
include_directories(${FL_INCLUDE_DIRS})
|
||||
else()
|
||||
include_directories(${Boost_INCLUDE_DIRS} ${CMAKE_HOME_DIRECTORY} ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_HOME_DIRECTORY}/lib ${CMAKE_HOME_DIRECTORY}/AI/FuzzyLite/fuzzylite)
|
||||
include_directories(${CMAKE_HOME_DIRECTORY}/AI/FuzzyLite/fuzzylite)
|
||||
endif()
|
||||
include_directories(${Boost_INCLUDE_DIRS} ${CMAKE_HOME_DIRECTORY} ${CMAKE_HOME_DIRECTORY}/include ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_HOME_DIRECTORY}/lib)
|
||||
|
||||
set(VCAI_SRCS
|
||||
StdInc.cpp
|
||||
VCAI.cpp
|
||||
Goals.cpp
|
||||
AIUtility.cpp
|
||||
main.cpp
|
||||
Fuzzy.cpp
|
||||
StdInc.cpp
|
||||
VCAI.cpp
|
||||
Goals.cpp
|
||||
AIUtility.cpp
|
||||
main.cpp
|
||||
Fuzzy.cpp
|
||||
)
|
||||
|
||||
add_library(VCAI SHARED ${VCAI_SRCS})
|
||||
|
@ -5,6 +5,8 @@
|
||||
#include "../../lib/mapObjects/MapObjects.h"
|
||||
#include "../../lib/mapObjects/CommonConstructors.h"
|
||||
#include "../../lib/CCreatureHandler.h"
|
||||
#include "../../lib/CPathfinder.h"
|
||||
#include "../../lib/CGameStateFwd.h"
|
||||
#include "../../lib/VCMI_Lib.h"
|
||||
#include "../../CCallback.h"
|
||||
#include "VCAI.h"
|
||||
@ -29,7 +31,6 @@ class Engine;
|
||||
class InputVariable;
|
||||
class CGTownInstance;
|
||||
|
||||
using namespace vstd;
|
||||
//using namespace Goals;
|
||||
|
||||
FuzzyHelper *fh;
|
||||
@ -45,7 +46,7 @@ engineBase::engineBase()
|
||||
void engineBase::configure()
|
||||
{
|
||||
engine.configure("Minimum", "Maximum", "Minimum", "AlgebraicSum", "Centroid");
|
||||
logAi->infoStream() << engine.toString();
|
||||
logAi->info(engine.toString());
|
||||
}
|
||||
|
||||
void engineBase::addRule(const std::string &txt)
|
||||
@ -83,7 +84,7 @@ armyStructure evaluateArmyStructure (const CArmedInstance * army)
|
||||
if (walker)
|
||||
walkersStrenght += s.second->getPower();
|
||||
|
||||
amax (maxSpeed, s.second->type->valOfBonuses(Bonus::STACKS_SPEED));
|
||||
vstd::amax(maxSpeed, s.second->type->valOfBonuses(Bonus::STACKS_SPEED));
|
||||
}
|
||||
armyStructure as;
|
||||
as.walkers = walkersStrenght / totalStrenght;
|
||||
@ -148,7 +149,7 @@ void FuzzyHelper::initTacticalAdvantage()
|
||||
{
|
||||
fl::Rectangle* none = new fl::Rectangle("NONE", CGTownInstance::NONE, CGTownInstance::NONE + (CGTownInstance::FORT - CGTownInstance::NONE) * 0.5f);
|
||||
ta.castleWalls->addTerm(none);
|
||||
|
||||
|
||||
fl::Trapezoid* medium = new fl::Trapezoid("MEDIUM", (CGTownInstance::FORT - CGTownInstance::NONE) * 0.5f, CGTownInstance::FORT,
|
||||
CGTownInstance::CITADEL, CGTownInstance::CITADEL + (CGTownInstance::CASTLE - CGTownInstance::CITADEL) * 0.5f);
|
||||
ta.castleWalls->addTerm(medium);
|
||||
@ -159,7 +160,7 @@ void FuzzyHelper::initTacticalAdvantage()
|
||||
ta.castleWalls->setRange(CGTownInstance::NONE, CGTownInstance::CASTLE);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
ta.bankPresent = new fl::InputVariable("Bank");
|
||||
ta.engine.addInputVariable(ta.bankPresent);
|
||||
@ -200,7 +201,7 @@ void FuzzyHelper::initTacticalAdvantage()
|
||||
}
|
||||
catch (fl::Exception & pe)
|
||||
{
|
||||
logAi->errorStream() << "initTacticalAdvantage " << ": " << pe.getWhat();
|
||||
logAi->error("initTacticalAdvantage: %s", pe.getWhat());
|
||||
}
|
||||
}
|
||||
|
||||
@ -261,7 +262,7 @@ float FuzzyHelper::getTacticalAdvantage (const CArmedInstance *we, const CArmedI
|
||||
}
|
||||
catch (fl::Exception & fe)
|
||||
{
|
||||
logAi->errorStream() << "getTacticalAdvantage " << ": " << fe.getWhat();
|
||||
logAi->error("getTacticalAdvantage: %s ",fe.getWhat());
|
||||
}
|
||||
|
||||
if (output < 0 || (output != output))
|
||||
@ -272,7 +273,7 @@ float FuzzyHelper::getTacticalAdvantage (const CArmedInstance *we, const CArmedI
|
||||
|
||||
for (int i = 0; i < boost::size(tab); i++)
|
||||
log << names[i] << ": " << tab[i]->getInputValue() << " ";
|
||||
logAi->errorStream() << log.str();
|
||||
logAi->error(log.str());
|
||||
assert(false);
|
||||
}
|
||||
|
||||
@ -295,13 +296,15 @@ FuzzyHelper::TacticalAdvantage::~TacticalAdvantage()
|
||||
delete threat;
|
||||
}
|
||||
|
||||
//shared_ptr<AbstractGoal> chooseSolution (std::vector<shared_ptr<AbstractGoal>> & vec)
|
||||
//std::shared_ptr<AbstractGoal> chooseSolution (std::vector<std::shared_ptr<AbstractGoal>> & vec)
|
||||
|
||||
Goals::TSubgoal FuzzyHelper::chooseSolution (Goals::TGoalVec vec)
|
||||
{
|
||||
if (vec.empty()) //no possibilities found
|
||||
return sptr(Goals::Invalid());
|
||||
|
||||
ai->cachedSectorMaps.clear();
|
||||
|
||||
//a trick to switch between heroes less often - calculatePaths is costly
|
||||
auto sortByHeroes = [](const Goals::TSubgoal & lhs, const Goals::TSubgoal & rhs) -> bool
|
||||
{
|
||||
@ -407,7 +410,7 @@ void FuzzyHelper::initVisitTile()
|
||||
}
|
||||
catch (fl::Exception & fe)
|
||||
{
|
||||
logAi->errorStream() << "visitTile " << ": " << fe.getWhat();
|
||||
logAi->error("visitTile: %s",fe.getWhat());
|
||||
}
|
||||
}
|
||||
|
||||
@ -419,7 +422,7 @@ float FuzzyHelper::evaluate (Goals::VisitTile & g)
|
||||
|
||||
//assert(cb->isInTheMap(g.tile));
|
||||
float turns = 0;
|
||||
float distance = cb->getMovementCost(g.hero.h, g.tile);
|
||||
float distance = CPathfinderHelper::getMovementCost(g.hero.h, g.tile);
|
||||
if (!distance) //we stand on that tile
|
||||
turns = 0;
|
||||
else
|
||||
@ -452,11 +455,10 @@ float FuzzyHelper::evaluate (Goals::VisitTile & g)
|
||||
}
|
||||
catch (fl::Exception & fe)
|
||||
{
|
||||
logAi->errorStream() << "evaluate VisitTile " << ": " << fe.getWhat();
|
||||
logAi->error("evaluate VisitTile: %s",fe.getWhat());
|
||||
}
|
||||
assert (g.priority >= 0);
|
||||
return g.priority;
|
||||
|
||||
}
|
||||
float FuzzyHelper::evaluate (Goals::VisitHero & g)
|
||||
{
|
||||
@ -465,7 +467,7 @@ float FuzzyHelper::evaluate (Goals::VisitHero & g)
|
||||
return -100; //hero died in the meantime
|
||||
//TODO: consider direct copy (constructor?)
|
||||
g.setpriority(Goals::VisitTile(obj->visitablePos()).sethero(g.hero).setisAbstract(g.isAbstract).accept(this));
|
||||
return g.priority;
|
||||
return g.priority;
|
||||
}
|
||||
float FuzzyHelper::evaluate (Goals::GatherArmy & g)
|
||||
{
|
||||
@ -480,8 +482,7 @@ float FuzzyHelper::evaluate (Goals::ClearWayTo & g)
|
||||
if (!g.hero.h)
|
||||
throw cannotFulfillGoalException("ClearWayTo called without hero!");
|
||||
|
||||
SectorMap sm(g.hero);
|
||||
int3 t = sm.firstTileToGet(g.hero, g.tile);
|
||||
int3 t = ai->getCachedSectorMap(g.hero)->firstTileToGet(g.hero, g.tile);
|
||||
|
||||
if (t.valid())
|
||||
{
|
||||
@ -523,7 +524,7 @@ float FuzzyHelper::evaluate (Goals::Invalid & g)
|
||||
}
|
||||
float FuzzyHelper::evaluate (Goals::AbstractGoal & g)
|
||||
{
|
||||
logAi->warnStream() << boost::format("Cannot evaluate goal %s") % g.name();
|
||||
logAi->warn("Cannot evaluate goal %s", g.name());
|
||||
return g.priority;
|
||||
}
|
||||
void FuzzyHelper::setPriority (Goals::TSubgoal & g)
|
||||
|
@ -15,6 +15,7 @@
|
||||
class VCAI;
|
||||
class CArmedInstance;
|
||||
class CBank;
|
||||
struct SectorMap;
|
||||
|
||||
class engineBase
|
||||
{
|
||||
@ -54,6 +55,8 @@ class FuzzyHelper
|
||||
~EvalVisitTile();
|
||||
} vt;
|
||||
|
||||
|
||||
|
||||
public:
|
||||
enum RuleBlocks {BANK_DANGER, TACTICAL_ADVANTAGE, VISIT_TILE};
|
||||
//blocks should be initialized in this order, which may be confusing :/
|
||||
@ -80,5 +83,5 @@ public:
|
||||
float getTacticalAdvantage (const CArmedInstance *we, const CArmedInstance *enemy); //returns factor how many times enemy is stronger than us
|
||||
|
||||
Goals::TSubgoal chooseSolution (Goals::TGoalVec vec);
|
||||
//shared_ptr<AbstractGoal> chooseSolution (std::vector<shared_ptr<AbstractGoal>> & vec);
|
||||
//std::shared_ptr<AbstractGoal> chooseSolution (std::vector<std::shared_ptr<AbstractGoal>> & vec);
|
||||
};
|
||||
|
@ -3,6 +3,7 @@
|
||||
#include "VCAI.h"
|
||||
#include "Fuzzy.h"
|
||||
#include "../../lib/mapping/CMap.h" //for victory conditions
|
||||
#include "../../lib/CPathfinder.h"
|
||||
|
||||
/*
|
||||
* Goals.cpp, part of VCMI engine
|
||||
@ -18,12 +19,11 @@ extern boost::thread_specific_ptr<CCallback> cb;
|
||||
extern boost::thread_specific_ptr<VCAI> ai;
|
||||
extern FuzzyHelper * fh; //TODO: this logic should be moved inside VCAI
|
||||
|
||||
using namespace vstd;
|
||||
using namespace Goals;
|
||||
|
||||
TSubgoal Goals::sptr(const AbstractGoal & tmp)
|
||||
{
|
||||
shared_ptr<AbstractGoal> ptr;
|
||||
std::shared_ptr<AbstractGoal> ptr;
|
||||
ptr.reset(tmp.clone());
|
||||
return ptr;
|
||||
}
|
||||
@ -154,8 +154,8 @@ bool Goals::AbstractGoal::operator== (AbstractGoal &g)
|
||||
|
||||
//TODO: find out why the following are not generated automatically on MVS?
|
||||
|
||||
namespace Goals
|
||||
{
|
||||
namespace Goals
|
||||
{
|
||||
template <>
|
||||
void CGoal<Win>::accept (VCAI * ai)
|
||||
{
|
||||
@ -182,8 +182,8 @@ namespace Goals
|
||||
|
||||
//TSubgoal AbstractGoal::whatToDoToAchieve()
|
||||
//{
|
||||
// logAi->debugStream() << boost::format("Decomposing goal of type %s") % name();
|
||||
// return sptr (Goals::Explore());
|
||||
// logAi->debug("Decomposing goal of type %s",name());
|
||||
// return sptr (Goals::Explore());
|
||||
//}
|
||||
|
||||
TSubgoal Win::whatToDoToAchieve()
|
||||
@ -275,7 +275,7 @@ TSubgoal Win::whatToDoToAchieve()
|
||||
// 0.85 -> radius now 2 tiles
|
||||
// 0.95 -> 1 tile radius, position is fully known
|
||||
// AFAIK H3 AI does something like this
|
||||
int3 grailPos = cb->getGrailPos(ratio);
|
||||
int3 grailPos = cb->getGrailPos(&ratio);
|
||||
if(ratio > 0.99)
|
||||
{
|
||||
return sptr (Goals::DigAtTile(grailPos));
|
||||
@ -367,7 +367,7 @@ TSubgoal FindObj::whatToDoToAchieve()
|
||||
|
||||
std::string GetObj::completeMessage() const
|
||||
{
|
||||
return "hero " + hero.get()->name + " captured Object ID = " + boost::lexical_cast<std::string>(objid);
|
||||
return "hero " + hero.get()->name + " captured Object ID = " + boost::lexical_cast<std::string>(objid);
|
||||
}
|
||||
|
||||
TSubgoal GetObj::whatToDoToAchieve()
|
||||
@ -409,7 +409,7 @@ bool GetObj::fulfillsMe (TSubgoal goal)
|
||||
|
||||
std::string VisitHero::completeMessage() const
|
||||
{
|
||||
return "hero " + hero.get()->name + " visited hero " + boost::lexical_cast<std::string>(objid);
|
||||
return "hero " + hero.get()->name + " visited hero " + boost::lexical_cast<std::string>(objid);
|
||||
}
|
||||
|
||||
TSubgoal VisitHero::whatToDoToAchieve()
|
||||
@ -422,7 +422,7 @@ TSubgoal VisitHero::whatToDoToAchieve()
|
||||
if (hero && ai->isAccessibleForHero(pos, hero, true) && isSafeToVisit(hero, pos)) //enemy heroes can get reinforcements
|
||||
{
|
||||
if (hero->pos == pos)
|
||||
logAi->errorStream() << "Hero " << hero.name << " tries to visit himself.";
|
||||
logAi->error("Hero %s tries to visit himself.", hero.name);
|
||||
else
|
||||
{
|
||||
//can't use VISIT_TILE here as tile appears blocked by target hero
|
||||
@ -435,10 +435,17 @@ TSubgoal VisitHero::whatToDoToAchieve()
|
||||
|
||||
bool VisitHero::fulfillsMe (TSubgoal goal)
|
||||
{
|
||||
if (goal->goalType == Goals::VISIT_TILE && cb->getObj(ObjectInstanceID(objid))->visitablePos() == goal->tile)
|
||||
return true;
|
||||
else
|
||||
if (goal->goalType != Goals::VISIT_TILE)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
auto obj = cb->getObj(ObjectInstanceID(objid));
|
||||
if (!obj)
|
||||
{
|
||||
logAi->error("Hero %s: VisitHero::fulfillsMe at %s: object %d not found", hero.name, goal->tile, objid);
|
||||
return false;
|
||||
}
|
||||
return obj->visitablePos() == goal->tile;
|
||||
}
|
||||
|
||||
TSubgoal GetArtOfType::whatToDoToAchieve()
|
||||
@ -454,11 +461,11 @@ TSubgoal ClearWayTo::whatToDoToAchieve()
|
||||
assert(cb->isInTheMap(tile)); //set tile
|
||||
if(!cb->isVisible(tile))
|
||||
{
|
||||
logAi->errorStream() << "Clear way should be used with visible tiles!";
|
||||
logAi->error("Clear way should be used with visible tiles!");
|
||||
return sptr (Goals::Explore());
|
||||
}
|
||||
|
||||
return (fh->chooseSolution(getAllPossibleSubgoals()));
|
||||
return (fh->chooseSolution(getAllPossibleSubgoals()));
|
||||
}
|
||||
|
||||
TGoalVec ClearWayTo::getAllPossibleSubgoals()
|
||||
@ -483,9 +490,9 @@ TGoalVec ClearWayTo::getAllPossibleSubgoals()
|
||||
|
||||
//if our hero is trapped, make sure we request clearing the way from OUR perspective
|
||||
|
||||
SectorMap sm(h);
|
||||
auto sm = ai->getCachedSectorMap(h);
|
||||
|
||||
int3 tileToHit = sm.firstTileToGet(h, tile);
|
||||
int3 tileToHit = sm->firstTileToGet(h, tile);
|
||||
if (!tileToHit.valid())
|
||||
continue;
|
||||
|
||||
@ -505,7 +512,7 @@ TGoalVec ClearWayTo::getAllPossibleSubgoals()
|
||||
|
||||
if (topObj->ID == Obj::HERO && cb->getPlayerRelations(h->tempOwner, topObj->tempOwner) != PlayerRelations::ENEMIES)
|
||||
if (topObj != hero.get(true)) //the hero we want to free
|
||||
logAi->errorStream() << boost::format("%s stands in the way of %s") % topObj->getObjectName() % h->getObjectName();
|
||||
logAi->error("%s stands in the way of %s", topObj->getObjectName(), h->getObjectName());
|
||||
if (topObj->ID == Obj::QUEST_GUARD || topObj->ID == Obj::BORDERGUARD)
|
||||
{
|
||||
if (shouldVisit(h, topObj))
|
||||
@ -517,11 +524,11 @@ TGoalVec ClearWayTo::getAllPossibleSubgoals()
|
||||
else
|
||||
{
|
||||
//TODO: we should be able to return apriopriate quest here (VCAI::striveToQuest)
|
||||
logAi->debugStream() << "Quest guard blocks the way to " + tile();
|
||||
logAi->debug("Quest guard blocks the way to %s", tile());
|
||||
continue; //do not access quets guard if we can't complete the quest
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isSafeToVisit(h, tileToHit)) //this makes sense only if tile is guarded, but there i no quest object
|
||||
{
|
||||
ret.push_back (sptr (Goals::VisitTile(tileToHit).sethero(h)));
|
||||
@ -537,7 +544,7 @@ TGoalVec ClearWayTo::getAllPossibleSubgoals()
|
||||
|
||||
if (ret.empty())
|
||||
{
|
||||
logAi->warnStream() << "There is no known way to clear the way to tile " + tile();
|
||||
logAi->warn("There is no known way to clear the way to tile %s",tile());
|
||||
throw goalFulfilledException (sptr(Goals::ClearWayTo(tile))); //make sure asigned hero gets unlocked
|
||||
}
|
||||
|
||||
@ -574,7 +581,7 @@ TGoalVec Explore::getAllPossibleSubgoals()
|
||||
{
|
||||
//heroes = ai->getUnblockedHeroes();
|
||||
heroes = cb->getHeroesInfo();
|
||||
erase_if (heroes, [](const HeroPtr h)
|
||||
vstd::erase_if(heroes, [](const HeroPtr h)
|
||||
{
|
||||
if (ai->getGoal(h)->goalType == Goals::EXPLORE) //do not reassign hero who is already explorer
|
||||
return true;
|
||||
@ -633,11 +640,11 @@ TGoalVec Explore::getAllPossibleSubgoals()
|
||||
|
||||
for (auto h : heroes)
|
||||
{
|
||||
SectorMap sm(h);
|
||||
auto sm = ai->getCachedSectorMap(h);
|
||||
|
||||
for (auto obj : objs) //double loop, performance risk?
|
||||
{
|
||||
auto t = sm.firstTileToGet(h, obj->visitablePos()); //we assume that no more than one tile on the way is guarded
|
||||
auto t = sm->firstTileToGet(h, obj->visitablePos()); //we assume that no more than one tile on the way is guarded
|
||||
if (ai->isTileNotReserved(h, t))
|
||||
ret.push_back (sptr(Goals::ClearWayTo(obj->visitablePos(), h).setisAbstract(true)));
|
||||
}
|
||||
@ -692,8 +699,8 @@ TSubgoal RecruitHero::whatToDoToAchieve()
|
||||
if(!t)
|
||||
return sptr (Goals::BuildThis(BuildingID::TAVERN));
|
||||
|
||||
if(cb->getResourceAmount(Res::GOLD) < HERO_GOLD_COST)
|
||||
return sptr (Goals::CollectRes(Res::GOLD, HERO_GOLD_COST));
|
||||
if(cb->getResourceAmount(Res::GOLD) < GameConstants::HERO_GOLD_COST)
|
||||
return sptr (Goals::CollectRes(Res::GOLD, GameConstants::HERO_GOLD_COST));
|
||||
|
||||
return iAmElementar();
|
||||
}
|
||||
@ -746,10 +753,10 @@ TGoalVec VisitTile::getAllPossibleSubgoals()
|
||||
if (ai->canRecruitAnyHero())
|
||||
ret.push_back (sptr(Goals::RecruitHero()));
|
||||
}
|
||||
if (ret.empty())
|
||||
if(ret.empty())
|
||||
{
|
||||
auto obj = frontOrNull(cb->getVisitableObjs(tile));
|
||||
if (obj && obj->ID == Obj::HERO && obj->tempOwner == ai->playerID) //our own hero stands on that tile
|
||||
auto obj = vstd::frontOrNull(cb->getVisitableObjs(tile));
|
||||
if(obj && obj->ID == Obj::HERO && obj->tempOwner == ai->playerID) //our own hero stands on that tile
|
||||
{
|
||||
if (hero.get(true) && hero->id == obj->id) //if it's assigned hero, visit tile. If it's different hero, we can't visit tile now
|
||||
ret.push_back(sptr(Goals::VisitTile(tile).sethero(dynamic_cast<const CGHeroInstance *>(obj)).setisElementar(true)));
|
||||
@ -766,7 +773,7 @@ TGoalVec VisitTile::getAllPossibleSubgoals()
|
||||
|
||||
TSubgoal DigAtTile::whatToDoToAchieve()
|
||||
{
|
||||
const CGObjectInstance *firstObj = frontOrNull(cb->getVisitableObjs(tile));
|
||||
const CGObjectInstance *firstObj = vstd::frontOrNull(cb->getVisitableObjs(tile));
|
||||
if(firstObj && firstObj->ID == Obj::HERO && firstObj->tempOwner == ai->playerID) //we have hero at dest
|
||||
{
|
||||
const CGHeroInstance *h = dynamic_cast<const CGHeroInstance *>(firstObj);
|
||||
@ -862,7 +869,7 @@ TSubgoal GatherTroops::whatToDoToAchieve()
|
||||
{
|
||||
auto creatures = vstd::tryAt(t->town->creatures, creature->level - 1);
|
||||
if(!creatures)
|
||||
continue;
|
||||
continue;
|
||||
|
||||
int upgradeNumber = vstd::find_pos(*creatures, creature->idNumber);
|
||||
if(upgradeNumber < 0)
|
||||
@ -957,13 +964,13 @@ TGoalVec Conquer::getAllPossibleSubgoals()
|
||||
std::vector<const CGObjectInstance *> objs;
|
||||
for (auto obj : ai->visitableObjs)
|
||||
{
|
||||
if (conquerable(obj))
|
||||
if (conquerable(obj))
|
||||
objs.push_back (obj);
|
||||
}
|
||||
|
||||
for (auto h : cb->getHeroesInfo())
|
||||
{
|
||||
SectorMap sm(h);
|
||||
auto sm = ai->getCachedSectorMap(h);
|
||||
std::vector<const CGObjectInstance *> ourObjs(objs); //copy common objects
|
||||
|
||||
for (auto obj : ai->reservedHeroesMap[h]) //add objects reserved by this hero
|
||||
@ -971,11 +978,30 @@ TGoalVec Conquer::getAllPossibleSubgoals()
|
||||
if (conquerable(obj))
|
||||
ourObjs.push_back(obj);
|
||||
}
|
||||
for (auto obj : ourObjs) //double loop, performance risk?
|
||||
for (auto obj : ourObjs)
|
||||
{
|
||||
auto t = sm.firstTileToGet(h, obj->visitablePos()); //we assume that no more than one tile on the way is guarded
|
||||
if (ai->isTileNotReserved(h, t))
|
||||
ret.push_back (sptr(Goals::ClearWayTo(obj->visitablePos(), h).setisAbstract(true)));
|
||||
int3 dest = obj->visitablePos();
|
||||
auto t = sm->firstTileToGet(h, dest); //we assume that no more than one tile on the way is guarded
|
||||
if (t.valid()) //we know any path at all
|
||||
{
|
||||
if (ai->isTileNotReserved(h, t)) //no other hero wants to conquer that tile
|
||||
{
|
||||
if (isSafeToVisit(h, dest))
|
||||
{
|
||||
if (dest != t) //there is something blocking our way
|
||||
ret.push_back(sptr(Goals::ClearWayTo(dest, h).setisAbstract(true)));
|
||||
else
|
||||
{
|
||||
if (obj->ID.num == Obj::HERO) //enemy hero may move to other position
|
||||
ret.push_back(sptr(Goals::VisitHero(obj->id.getNum()).sethero(h).setisAbstract(true)));
|
||||
else //just visit that tile
|
||||
ret.push_back(sptr(Goals::VisitTile(dest).sethero(h).setisAbstract(true)));
|
||||
}
|
||||
}
|
||||
else //we need to get army in order to conquer that place
|
||||
ret.push_back(sptr(Goals::GatherArmy(evaluateDanger(dest, h) * SAFE_ATTACK_CONSTANT).sethero(h).setisAbstract(true)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!objs.empty() && ai->canRecruitAnyHero()) //probably no point to recruit hero if we see no objects to capture
|
||||
@ -1008,11 +1034,15 @@ TSubgoal GatherArmy::whatToDoToAchieve()
|
||||
|
||||
return fh->chooseSolution (getAllPossibleSubgoals()); //find dwelling. use current hero to prevent him from doing nothing.
|
||||
}
|
||||
|
||||
static const BuildingID unitsSource[] = { BuildingID::DWELL_LVL_1, BuildingID::DWELL_LVL_2, BuildingID::DWELL_LVL_3,
|
||||
BuildingID::DWELL_LVL_4, BuildingID::DWELL_LVL_5, BuildingID::DWELL_LVL_6, BuildingID::DWELL_LVL_7};
|
||||
|
||||
TGoalVec GatherArmy::getAllPossibleSubgoals()
|
||||
{
|
||||
//get all possible towns, heroes and dwellings we may use
|
||||
TGoalVec ret;
|
||||
|
||||
|
||||
//TODO: include evaluation of monsters gather in calculation
|
||||
for (auto t : cb->getTownsInfo())
|
||||
{
|
||||
@ -1033,7 +1063,7 @@ TGoalVec GatherArmy::getAllPossibleSubgoals()
|
||||
|
||||
auto otherHeroes = cb->getHeroesInfo();
|
||||
auto heroDummy = hero;
|
||||
erase_if(otherHeroes, [heroDummy](const CGHeroInstance * h)
|
||||
vstd::erase_if(otherHeroes, [heroDummy](const CGHeroInstance * h)
|
||||
{
|
||||
return (h == heroDummy.h || !ai->isAccessibleForHero(heroDummy->visitablePos(), h, true)
|
||||
|| !ai->canGetArmy(heroDummy.h, h) || ai->getGoal(h)->goalType == Goals::GATHER_ARMY);
|
||||
@ -1074,11 +1104,11 @@ TGoalVec GatherArmy::getAllPossibleSubgoals()
|
||||
}
|
||||
for(auto h : cb->getHeroesInfo())
|
||||
{
|
||||
SectorMap sm(h);
|
||||
auto sm = ai->getCachedSectorMap(h);
|
||||
for (auto obj : objs)
|
||||
{ //find safe dwelling
|
||||
auto pos = obj->visitablePos();
|
||||
if (ai->isGoodForVisit(obj, h, sm))
|
||||
if (ai->isGoodForVisit(obj, h, *sm))
|
||||
ret.push_back (sptr (Goals::VisitTile(pos).sethero(h)));
|
||||
}
|
||||
}
|
||||
@ -1098,7 +1128,7 @@ TGoalVec GatherArmy::getAllPossibleSubgoals()
|
||||
|
||||
//TSubgoal AbstractGoal::whatToDoToAchieve()
|
||||
//{
|
||||
// logAi->debugStream() << boost::format("Decomposing goal of type %s") % name();
|
||||
// logAi->debug("Decomposing goal of type %s",name());
|
||||
// return sptr (Goals::Explore());
|
||||
//}
|
||||
|
||||
|
@ -21,7 +21,7 @@ class FuzzyHelper;
|
||||
|
||||
namespace Goals
|
||||
{
|
||||
struct AbstractGoal;
|
||||
class AbstractGoal;
|
||||
class VisitTile;
|
||||
typedef std::shared_ptr<Goals::AbstractGoal> TSubgoal;
|
||||
typedef std::vector<TSubgoal> TGoalVec;
|
||||
@ -86,8 +86,10 @@ public:
|
||||
value = 0;
|
||||
aid = -1;
|
||||
resID = -1;
|
||||
objid = -1;
|
||||
tile = int3(-1, -1, -1);
|
||||
town = nullptr;
|
||||
bid = -1;
|
||||
}
|
||||
virtual ~AbstractGoal(){};
|
||||
//FIXME: abstract goal should be abstract, but serializer fails to instantiate subgoals in such case
|
||||
@ -107,7 +109,7 @@ public:
|
||||
static TSubgoal tryRecruitHero();
|
||||
|
||||
///Visitor pattern
|
||||
//TODO: make accept work for shared_ptr... somehow
|
||||
//TODO: make accept work for std::shared_ptr... somehow
|
||||
virtual void accept (VCAI * ai); //unhandled goal will report standard error
|
||||
virtual float accept (FuzzyHelper * f);
|
||||
|
||||
@ -134,6 +136,7 @@ public:
|
||||
isAbstract = false;
|
||||
value = 0;
|
||||
aid = -1;
|
||||
objid = -1;
|
||||
resID = -1;
|
||||
tile = int3(-1, -1, -1);
|
||||
town = nullptr;
|
||||
@ -161,7 +164,7 @@ public:
|
||||
TSubgoal iAmElementar()
|
||||
{
|
||||
setisElementar(true);
|
||||
shared_ptr<AbstractGoal> ptr;
|
||||
std::shared_ptr<AbstractGoal> ptr;
|
||||
ptr.reset(clone());
|
||||
return ptr;
|
||||
}
|
||||
@ -300,7 +303,7 @@ public:
|
||||
VisitHero(int hid) : CGoal (Goals::VISIT_HERO){objid = hid; priority = 4;};
|
||||
TGoalVec getAllPossibleSubgoals() override {return TGoalVec();};
|
||||
TSubgoal whatToDoToAchieve() override;
|
||||
//bool operator== (VisitHero &g) {return g.objid == objid;}
|
||||
bool operator== (VisitHero &g) { return g.goalType == goalType && g.objid == objid; }
|
||||
bool fulfillsMe (TSubgoal goal) override;
|
||||
std::string completeMessage() const override;
|
||||
};
|
||||
@ -322,7 +325,7 @@ public:
|
||||
VisitTile(int3 Tile) : CGoal (Goals::VISIT_TILE) {tile = Tile; priority = 5;};
|
||||
TGoalVec getAllPossibleSubgoals() override;
|
||||
TSubgoal whatToDoToAchieve() override;
|
||||
//bool operator== (VisitTile &g) {return g.tile == tile;}
|
||||
bool operator== (VisitTile &g) { return g.goalType == goalType && g.tile == tile; }
|
||||
std::string completeMessage() const override;
|
||||
};
|
||||
class ClearWayTo : public CGoal<ClearWayTo>
|
||||
@ -334,7 +337,7 @@ public:
|
||||
ClearWayTo(int3 Tile, HeroPtr h) : CGoal (Goals::CLEAR_WAY_TO) {tile = Tile; hero = h; priority = 5;};
|
||||
TGoalVec getAllPossibleSubgoals() override;
|
||||
TSubgoal whatToDoToAchieve() override;
|
||||
bool operator== (ClearWayTo &g) {return g.tile == tile;}
|
||||
bool operator== (ClearWayTo &g) { return g.goalType == goalType && g.tile == tile; }
|
||||
};
|
||||
class DigAtTile : public CGoal<DigAtTile>
|
||||
//elementar with hero on tile
|
||||
@ -345,7 +348,7 @@ public:
|
||||
DigAtTile(int3 Tile) : CGoal (Goals::DIG_AT_TILE) {tile = Tile; priority = 20;};
|
||||
TGoalVec getAllPossibleSubgoals() override {return TGoalVec();};
|
||||
TSubgoal whatToDoToAchieve() override;
|
||||
bool operator== (DigAtTile &g) {return g.tile == tile;}
|
||||
bool operator== (DigAtTile &g) { return g.goalType == goalType && g.tile == tile; }
|
||||
};
|
||||
|
||||
class CIssueCommand : public CGoal<CIssueCommand>
|
||||
|
@ -6,23 +6,25 @@
|
||||
<Option pch_mode="2" />
|
||||
<Option compiler="gcc" />
|
||||
<Build>
|
||||
<Target title="Debug-win32-SDL2">
|
||||
<Target title="Debug-win32">
|
||||
<Option platforms="Windows;" />
|
||||
<Option output="../VCAI" imp_lib="$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).a" def_file="$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).def" prefix_auto="1" extension_auto="1" />
|
||||
<Option object_output="obj/Debug/" />
|
||||
<Option object_output="obj/Debug/x86" />
|
||||
<Option type="3" />
|
||||
<Option compiler="gcc" />
|
||||
<Compiler>
|
||||
<Add option="-Og" />
|
||||
<Add option="-g" />
|
||||
</Compiler>
|
||||
<Linker>
|
||||
<Add directory="../FuzzyLite/bin/Debug" />
|
||||
<Add directory="../" />
|
||||
<Add directory="$(#boost.lib32)" />
|
||||
</Linker>
|
||||
</Target>
|
||||
<Target title="Release-win32-SDL2">
|
||||
<Target title="Release-win32">
|
||||
<Option platforms="Windows;" />
|
||||
<Option output="../VCAI" imp_lib="$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).a" def_file="$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).def" prefix_auto="1" extension_auto="1" />
|
||||
<Option object_output="obj/Release/" />
|
||||
<Option object_output="obj/Release/x86" />
|
||||
<Option type="3" />
|
||||
<Option compiler="gcc" />
|
||||
<Compiler>
|
||||
@ -31,35 +33,23 @@
|
||||
</Compiler>
|
||||
<Linker>
|
||||
<Add option="-s" />
|
||||
<Add directory="../FuzzyLite/bin/Release" />
|
||||
<Add directory="../" />
|
||||
<Add directory="$(#boost.lib32)" />
|
||||
</Linker>
|
||||
</Target>
|
||||
<Target title="Debug-win32-SDL1">
|
||||
<Target title="Debug-win64">
|
||||
<Option platforms="Windows;" />
|
||||
<Option output="../VCAI" imp_lib="$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).a" def_file="$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).def" prefix_auto="1" extension_auto="1" />
|
||||
<Option object_output="obj/Debug/" />
|
||||
<Option object_output="obj/Debug/x64" />
|
||||
<Option type="3" />
|
||||
<Option compiler="gcc" />
|
||||
<Option compiler="gnu_gcc_compiler_x64" />
|
||||
<Compiler>
|
||||
<Add option="-Og" />
|
||||
<Add option="-g" />
|
||||
</Compiler>
|
||||
<Linker>
|
||||
<Add directory="../FuzzyLite/bin/Debug" />
|
||||
</Linker>
|
||||
</Target>
|
||||
<Target title="Release-win32-SDL1">
|
||||
<Option platforms="Windows;" />
|
||||
<Option output="../VCAI" imp_lib="$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).a" def_file="$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).def" prefix_auto="1" extension_auto="1" />
|
||||
<Option object_output="obj/Release/" />
|
||||
<Option type="3" />
|
||||
<Option compiler="gcc" />
|
||||
<Compiler>
|
||||
<Add option="-fomit-frame-pointer" />
|
||||
<Add option="-O3" />
|
||||
</Compiler>
|
||||
<Linker>
|
||||
<Add option="-s" />
|
||||
<Add directory="../FuzzyLite/bin/Release" />
|
||||
<Add directory="../" />
|
||||
<Add directory="$(#boost.lib64)" />
|
||||
</Linker>
|
||||
</Target>
|
||||
</Build>
|
||||
@ -67,6 +57,7 @@
|
||||
<Add option="-pedantic" />
|
||||
<Add option="-Wextra" />
|
||||
<Add option="-Wall" />
|
||||
<Add option="-std=gnu++11" />
|
||||
<Add option="-fexceptions" />
|
||||
<Add option="-Wpointer-arith" />
|
||||
<Add option="-Wno-switch" />
|
||||
@ -86,7 +77,6 @@
|
||||
<Add option="-lboost_thread$(#boost.libsuffix)" />
|
||||
<Add option="-lboost_chrono$(#boost.libsuffix)" />
|
||||
<Add option="-lVCMI_lib" />
|
||||
<Add directory="$(#boost.lib32)" />
|
||||
<Add directory="../.." />
|
||||
</Linker>
|
||||
<Unit filename="AIUtility.cpp" />
|
||||
@ -96,6 +86,7 @@
|
||||
<Unit filename="Goals.cpp" />
|
||||
<Unit filename="Goals.h" />
|
||||
<Unit filename="StdInc.h">
|
||||
<Option compile="1" />
|
||||
<Option weight="0" />
|
||||
</Unit>
|
||||
<Unit filename="VCAI.cpp" />
|
||||
|
691
AI/VCAI/VCAI.cpp
691
AI/VCAI/VCAI.cpp
File diff suppressed because it is too large
Load Diff
@ -12,11 +12,8 @@
|
||||
#include "../../lib/CBuildingHandler.h"
|
||||
#include "../../lib/CCreatureHandler.h"
|
||||
#include "../../lib/CTownHandler.h"
|
||||
#include "../../lib/mapObjects/MiscObjects.h"
|
||||
#include "../../lib/spells/CSpellHandler.h"
|
||||
#include "../../lib/Connection.h"
|
||||
#include "../../lib/CGameState.h"
|
||||
#include "../../lib/mapping/CMap.h"
|
||||
#include "../../lib/NetPacks.h"
|
||||
#include "../../lib/CondSh.h"
|
||||
|
||||
struct QuestInfo;
|
||||
@ -81,7 +78,7 @@ struct SectorMap
|
||||
int id;
|
||||
std::vector<int3> tiles;
|
||||
std::vector<int3> embarkmentPoints; //tiles of other sectors onto which we can (dis)embark
|
||||
std::vector<const CGObjectInstance *> subterraneanGates;
|
||||
std::vector<const CGObjectInstance *> visitableObjs;
|
||||
bool water; //all tiles of sector are land or water
|
||||
Sector()
|
||||
{
|
||||
@ -95,6 +92,7 @@ struct SectorMap
|
||||
//std::vector<std::vector<std::vector<unsigned char>>> pathfinderSector;
|
||||
|
||||
std::map<int, Sector> infoOnSectors;
|
||||
std::shared_ptr<boost::multi_array<TerrainTile*, 3>> visibleTiles;
|
||||
|
||||
SectorMap();
|
||||
SectorMap(HeroPtr h);
|
||||
@ -103,7 +101,11 @@ struct SectorMap
|
||||
void exploreNewSector(crint3 pos, int num, CCallback * cbp);
|
||||
void write(crstring fname);
|
||||
|
||||
bool markIfBlocked(ui8 &sec, crint3 pos, const TerrainTile *t);
|
||||
bool markIfBlocked(ui8 &sec, crint3 pos);
|
||||
unsigned char &retreiveTile(crint3 pos);
|
||||
TerrainTile* getTile(crint3 pos) const;
|
||||
std::vector<const CGObjectInstance *> getNearbyObjs(HeroPtr h, bool sectorsAround);
|
||||
|
||||
void makeParentBFS(crint3 source);
|
||||
|
||||
@ -111,20 +113,6 @@ struct SectorMap
|
||||
int3 findFirstVisitableTile(HeroPtr h, crint3 dst);
|
||||
};
|
||||
|
||||
//Set of buildings for different goals. Does not include any prerequisites.
|
||||
const BuildingID essential[] = {BuildingID::TAVERN, BuildingID::TOWN_HALL};
|
||||
const BuildingID goldSource[] = {BuildingID::TOWN_HALL, BuildingID::CITY_HALL, BuildingID::CAPITOL};
|
||||
const BuildingID unitsSource[] = { BuildingID::DWELL_LVL_1, BuildingID::DWELL_LVL_2, BuildingID::DWELL_LVL_3,
|
||||
BuildingID::DWELL_LVL_4, BuildingID::DWELL_LVL_5, BuildingID::DWELL_LVL_6, BuildingID::DWELL_LVL_7};
|
||||
const BuildingID unitsUpgrade[] = { BuildingID::DWELL_LVL_1_UP, BuildingID::DWELL_LVL_2_UP, BuildingID::DWELL_LVL_3_UP,
|
||||
BuildingID::DWELL_LVL_4_UP, BuildingID::DWELL_LVL_5_UP, BuildingID::DWELL_LVL_6_UP, BuildingID::DWELL_LVL_7_UP};
|
||||
const BuildingID unitGrowth[] = { BuildingID::FORT, BuildingID::CITADEL, BuildingID::CASTLE, BuildingID::HORDE_1,
|
||||
BuildingID::HORDE_1_UPGR, BuildingID::HORDE_2, BuildingID::HORDE_2_UPGR};
|
||||
const BuildingID spells[] = {BuildingID::MAGES_GUILD_1, BuildingID::MAGES_GUILD_2, BuildingID::MAGES_GUILD_3,
|
||||
BuildingID::MAGES_GUILD_4, BuildingID::MAGES_GUILD_5};
|
||||
const BuildingID extra[] = {BuildingID::RESOURCE_SILO, BuildingID::SPECIAL_1, BuildingID::SPECIAL_2, BuildingID::SPECIAL_3,
|
||||
BuildingID::SPECIAL_4, BuildingID::SHIPYARD}; // all remaining buildings
|
||||
|
||||
class VCAI : public CAdventureAI
|
||||
{
|
||||
public:
|
||||
@ -141,9 +129,10 @@ public:
|
||||
|
||||
friend class FuzzyHelper;
|
||||
|
||||
std::map<TeleportChannelID, shared_ptr<TeleportChannel> > knownTeleportChannels;
|
||||
std::map<TeleportChannelID, std::shared_ptr<TeleportChannel> > knownTeleportChannels;
|
||||
std::map<const CGObjectInstance *, const CGObjectInstance *> knownSubterraneanGates;
|
||||
ObjectInstanceID destinationTeleport;
|
||||
int3 destinationTeleportPos;
|
||||
std::vector<ObjectInstanceID> teleportChannelProbingList; //list of teleport channel exits that not visible and need to be (re-)explored
|
||||
//std::vector<const CGObjectInstance *> visitedThisWeek; //only OPWs
|
||||
std::map<HeroPtr, std::set<const CGTownInstance *> > townVisitsThisWeek;
|
||||
@ -157,17 +146,19 @@ public:
|
||||
std::set<const CGObjectInstance *> alreadyVisited;
|
||||
std::set<const CGObjectInstance *> reservedObjs; //to be visited by specific hero
|
||||
|
||||
std::map <HeroPtr, std::shared_ptr<SectorMap>> cachedSectorMaps; //TODO: serialize? not necessary
|
||||
|
||||
TResources saving;
|
||||
|
||||
AIStatus status;
|
||||
std::string battlename;
|
||||
|
||||
shared_ptr<CCallback> myCb;
|
||||
std::shared_ptr<CCallback> myCb;
|
||||
|
||||
unique_ptr<boost::thread> makingTurn;
|
||||
std::unique_ptr<boost::thread> makingTurn;
|
||||
|
||||
VCAI(void);
|
||||
~VCAI(void);
|
||||
virtual ~VCAI(void);
|
||||
|
||||
//TODO: use only smart pointers?
|
||||
void tryRealize(Goals::Explore & g);
|
||||
@ -189,16 +180,16 @@ public:
|
||||
|
||||
virtual std::string getBattleAIName() const override;
|
||||
|
||||
virtual void init(shared_ptr<CCallback> CB) override;
|
||||
virtual void init(std::shared_ptr<CCallback> CB) override;
|
||||
virtual void yourTurn() override;
|
||||
|
||||
virtual void heroGotLevel(const CGHeroInstance *hero, PrimarySkill::PrimarySkill pskill, std::vector<SecondarySkill> &skills, QueryID queryID) override; //pskill is gained primary skill, interface has to choose one of given skills and call callback with selection id
|
||||
virtual void commanderGotLevel (const CCommanderInstance * commander, std::vector<ui32> skills, QueryID queryID) override; //TODO
|
||||
virtual void showBlockingDialog(const std::string &text, const std::vector<Component> &components, QueryID askID, const int soundID, bool selection, bool cancel) override; //Show a dialog, player must take decision. If selection then he has to choose between one of given components, if cancel he is allowed to not choose. After making choice, CCallback::selectionMade should be called with number of selected component (1 - n) or 0 for cancel (if allowed) and askID.
|
||||
virtual void showGarrisonDialog(const CArmedInstance *up, const CGHeroInstance *down, bool removableUnits, QueryID queryID) override; //all stacks operations between these objects become allowed, interface has to call onEnd when done
|
||||
virtual void showTeleportDialog(TeleportChannelID channel, std::vector<ObjectInstanceID> exits, bool impassable, QueryID askID) override;
|
||||
virtual void saveGame(COSer & h, const int version) override; //saving
|
||||
virtual void loadGame(CISer & h, const int version) override; //loading
|
||||
virtual void showTeleportDialog(TeleportChannelID channel, TTeleportExitsList exits, bool impassable, QueryID askID) override;
|
||||
virtual void saveGame(BinarySerializer & h, const int version) override; //saving
|
||||
virtual void loadGame(BinaryDeserializer & h, const int version) override; //loading
|
||||
virtual void finish() override;
|
||||
|
||||
virtual void availableCreaturesChanged(const CGDwelling *town) override;
|
||||
@ -268,7 +259,6 @@ public:
|
||||
|
||||
void recruitHero(const CGTownInstance * t, bool throwing = false);
|
||||
bool isGoodForVisit(const CGObjectInstance *obj, HeroPtr h, SectorMap &sm);
|
||||
std::vector<const CGObjectInstance *> getPossibleDestinations(HeroPtr h);
|
||||
void buildStructure(const CGTownInstance * t);
|
||||
//void recruitCreatures(const CGTownInstance * t);
|
||||
void recruitCreatures(const CGDwelling * d, const CArmedInstance * recruiter);
|
||||
@ -292,7 +282,7 @@ public:
|
||||
void markHeroUnableToExplore (HeroPtr h);
|
||||
void markHeroAbleToExplore (HeroPtr h);
|
||||
bool isAbleToExplore (HeroPtr h);
|
||||
void clearHeroesUnableToExplore();
|
||||
void clearPathsInfo();
|
||||
|
||||
void validateObject(const CGObjectInstance *obj); //checks if object is still visible and if not, removes references to it
|
||||
void validateObject(ObjectIdRef obj); //checks if object is still visible and if not, removes references to it
|
||||
@ -307,6 +297,8 @@ public:
|
||||
|
||||
const CGObjectInstance *getUnvisitedObj(const std::function<bool(const CGObjectInstance *)> &predicate);
|
||||
bool isAccessibleForHero(const int3 & pos, HeroPtr h, bool includeAllies = false) const;
|
||||
//optimization - use one SM for every hero call
|
||||
std::shared_ptr<SectorMap> getCachedSectorMap(HeroPtr h);
|
||||
|
||||
const CGTownInstance *findTownWithTavern() const;
|
||||
bool canRecruitAnyHero(const CGTownInstance * t = NULL) const;
|
||||
|
@ -23,7 +23,7 @@ extern "C" DLL_EXPORT void GetAiName(char* name)
|
||||
strcpy_s(name, strlen(g_cszAiName) + 1, g_cszAiName);
|
||||
}
|
||||
|
||||
extern "C" DLL_EXPORT void GetNewAI(shared_ptr<CGlobalAI> &out)
|
||||
extern "C" DLL_EXPORT void GetNewAI(std::shared_ptr<CGlobalAI> &out)
|
||||
{
|
||||
out = make_shared<VCAI>();
|
||||
out = std::make_shared<VCAI>();
|
||||
}
|
||||
|
7
AUTHORS
7
AUTHORS
@ -5,7 +5,7 @@ Michał Urbańczyk aka Tow, <impono@gmail.com>
|
||||
maintenance, reverse engineering, general support.
|
||||
|
||||
Mateusz B. aka Tow dragon, <matcio1@gmail.com>
|
||||
* general suport, battle support, support for many Heroes 3 config files, reverse engineering, ERM/VERM parser and interpreter
|
||||
* general support, battle support, support for many Heroes 3 config files, reverse engineering, ERM/VERM parser and interpreter
|
||||
|
||||
Stefan Pavlov aka Ste, <mailste@gmail.com>
|
||||
* minor fixes in pregame
|
||||
@ -52,5 +52,8 @@ Alexey aka Macron1Robot, <>
|
||||
Alexander Shishkin aka alexvins,
|
||||
* MinGW platform support, modding related programming
|
||||
|
||||
Arseniy Shestakov aka SXX,
|
||||
Arseniy Shestakov aka SXX, <me@arseniyshestakov.com>
|
||||
* pathfinding improvements, programming
|
||||
|
||||
Vadim Markovtsev, <gmarkhor@gmail.com>
|
||||
* resolving problems with macOS, bug fixes
|
||||
|
@ -12,18 +12,12 @@
|
||||
#include "lib/mapObjects/CObjectClassesHandler.h"
|
||||
#include "lib/CGeneralTextHandler.h"
|
||||
#include "lib/CHeroHandler.h"
|
||||
#include "lib/Connection.h"
|
||||
#include "lib/NetPacks.h"
|
||||
#include "client/mapHandler.h"
|
||||
#include "lib/spells/CSpellHandler.h"
|
||||
#include "lib/CArtHandler.h"
|
||||
#include "lib/GameConstants.h"
|
||||
#ifdef min
|
||||
#undef min
|
||||
#endif
|
||||
#ifdef max
|
||||
#undef max
|
||||
#endif
|
||||
#include "lib/CPlayerState.h"
|
||||
#include "lib/UnlockGuard.h"
|
||||
|
||||
/*
|
||||
@ -60,7 +54,7 @@ int CCallback::selectionMade(int selection, QueryID queryID)
|
||||
ASSERT_IF_CALLED_WITH_PLAYER
|
||||
if(queryID == QueryID(-1))
|
||||
{
|
||||
logGlobal->errorStream() << "Cannot answer the query -1!";
|
||||
logGlobal->errorStream() << "Cannot answer the query -1!";
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -71,7 +65,8 @@ int CCallback::selectionMade(int selection, QueryID queryID)
|
||||
|
||||
void CCallback::recruitCreatures(const CGDwelling *obj, const CArmedInstance * dst, CreatureID ID, ui32 amount, si32 level/*=-1*/)
|
||||
{
|
||||
if(player!=obj->tempOwner && obj->ID != Obj::WAR_MACHINE_FACTORY)
|
||||
// TODO exception for neutral dwellings shouldn't be hardcoded
|
||||
if(player != obj->tempOwner && obj->ID != Obj::WAR_MACHINE_FACTORY && obj->ID != Obj::REFUGEE_CAMP)
|
||||
return;
|
||||
|
||||
RecruitCreatures pack(obj->id, dst->id, ID, amount, level);
|
||||
@ -80,7 +75,7 @@ void CCallback::recruitCreatures(const CGDwelling *obj, const CArmedInstance * d
|
||||
|
||||
bool CCallback::dismissCreature(const CArmedInstance *obj, SlotID stackPos)
|
||||
{
|
||||
if(((player>=0) && obj->tempOwner != player) || (obj->stacksCount()<2 && obj->needsLastStack()))
|
||||
if((player && obj->tempOwner != player) || (obj->stacksCount()<2 && obj->needsLastStack()))
|
||||
return false;
|
||||
|
||||
DisbandCreature pack(stackPos,obj->id);
|
||||
@ -97,7 +92,7 @@ bool CCallback::upgradeCreature(const CArmedInstance *obj, SlotID stackPos, Crea
|
||||
|
||||
void CCallback::endTurn()
|
||||
{
|
||||
logGlobal->traceStream() << "Player " << *player << " ended his turn.";
|
||||
logGlobal->traceStream() << "Player " << *player << " ended his turn.";
|
||||
EndTurn pack;
|
||||
sendRequest(&pack); //report that we ended turn
|
||||
}
|
||||
@ -189,7 +184,7 @@ int CBattleCallback::sendRequest(const CPack *request)
|
||||
int requestID = cl->sendRequest(request, *player);
|
||||
if(waitTillRealize)
|
||||
{
|
||||
logGlobal->traceStream() << boost::format("We'll wait till request %d is answered.\n") % requestID;
|
||||
logGlobal->traceStream() << boost::format("We'll wait till request %d is answered.\n") % requestID;
|
||||
auto gsUnlocker = vstd::makeUnlockSharedGuardIf(getGsMutex(), unlockGsWhenWaiting);
|
||||
cl->waitingRequest.waitWhileContains(requestID);
|
||||
}
|
||||
@ -230,7 +225,6 @@ void CCallback::trade(const CGObjectInstance *market, EMarketMode::EMarketMode m
|
||||
|
||||
void CCallback::setFormation(const CGHeroInstance * hero, bool tight)
|
||||
{
|
||||
const_cast<CGHeroInstance*>(hero)-> formation = tight;
|
||||
SetFormation pack(hero->id,tight);
|
||||
sendRequest(&pack);
|
||||
}
|
||||
@ -290,11 +284,6 @@ bool CCallback::canMoveBetween(const int3 &a, const int3 &b)
|
||||
return gs->checkForVisitableDir(a, b) && gs->checkForVisitableDir(b, a);
|
||||
}
|
||||
|
||||
int CCallback::getMovementCost(const CGHeroInstance * hero, int3 dest)
|
||||
{
|
||||
return gs->getMovementCost(hero, hero->visitablePos(), dest, hero->hasBonusOfType (Bonus::FLYING_MOVEMENT), hero->movement);
|
||||
}
|
||||
|
||||
const CPathsInfo * CCallback::getPathsInfo(const CGHeroInstance *h)
|
||||
{
|
||||
return cl->getPathsInfo(h);
|
||||
@ -331,6 +320,8 @@ void CCallback::castSpell(const CGHeroInstance *hero, SpellID spellID, const int
|
||||
|
||||
void CCallback::unregisterAllInterfaces()
|
||||
{
|
||||
for (auto& pi : cl->playerint)
|
||||
pi.second->finish();
|
||||
cl->playerint.clear();
|
||||
cl->battleints.clear();
|
||||
}
|
||||
@ -343,22 +334,22 @@ int CCallback::mergeOrSwapStacks(const CArmedInstance *s1, const CArmedInstance
|
||||
return swapCreatures(s1, s2, p1, p2);
|
||||
}
|
||||
|
||||
void CCallback::registerGameInterface(shared_ptr<IGameEventsReceiver> gameEvents)
|
||||
void CCallback::registerGameInterface(std::shared_ptr<IGameEventsReceiver> gameEvents)
|
||||
{
|
||||
cl->additionalPlayerInts[*player].push_back(gameEvents);
|
||||
}
|
||||
|
||||
void CCallback::registerBattleInterface(shared_ptr<IBattleEventsReceiver> battleEvents)
|
||||
void CCallback::registerBattleInterface(std::shared_ptr<IBattleEventsReceiver> battleEvents)
|
||||
{
|
||||
cl->additionalBattleInts[*player].push_back(battleEvents);
|
||||
}
|
||||
|
||||
void CCallback::unregisterGameInterface(shared_ptr<IGameEventsReceiver> gameEvents)
|
||||
void CCallback::unregisterGameInterface(std::shared_ptr<IGameEventsReceiver> gameEvents)
|
||||
{
|
||||
cl->additionalPlayerInts[*player] -= gameEvents;
|
||||
}
|
||||
|
||||
void CCallback::unregisterBattleInterface(shared_ptr<IBattleEventsReceiver> battleEvents)
|
||||
void CCallback::unregisterBattleInterface(std::shared_ptr<IBattleEventsReceiver> battleEvents)
|
||||
{
|
||||
cl->additionalBattleInts[*player] -= battleEvents;
|
||||
}
|
||||
|
51
CCallback.h
51
CCallback.h
@ -104,49 +104,48 @@ public:
|
||||
|
||||
//client-specific functionalities (pathfinding)
|
||||
virtual bool canMoveBetween(const int3 &a, const int3 &b);
|
||||
virtual int getMovementCost(const CGHeroInstance * hero, int3 dest);
|
||||
virtual int3 getGuardingCreaturePosition(int3 tile);
|
||||
virtual const CPathsInfo * getPathsInfo(const CGHeroInstance *h);
|
||||
|
||||
virtual void calculatePaths(const CGHeroInstance *hero, CPathsInfo &out);
|
||||
|
||||
//Set of metrhods that allows adding more interfaces for this player that'll receive game event call-ins.
|
||||
void registerGameInterface(shared_ptr<IGameEventsReceiver> gameEvents);
|
||||
void registerBattleInterface(shared_ptr<IBattleEventsReceiver> battleEvents);
|
||||
void unregisterGameInterface(shared_ptr<IGameEventsReceiver> gameEvents);
|
||||
void unregisterBattleInterface(shared_ptr<IBattleEventsReceiver> battleEvents);
|
||||
void registerGameInterface(std::shared_ptr<IGameEventsReceiver> gameEvents);
|
||||
void registerBattleInterface(std::shared_ptr<IBattleEventsReceiver> battleEvents);
|
||||
void unregisterGameInterface(std::shared_ptr<IGameEventsReceiver> gameEvents);
|
||||
void unregisterBattleInterface(std::shared_ptr<IBattleEventsReceiver> battleEvents);
|
||||
|
||||
void unregisterAllInterfaces(); //stops delivering information about game events to player interfaces -> can be called ONLY after victory/loss
|
||||
|
||||
//commands
|
||||
bool moveHero(const CGHeroInstance *h, int3 dst, bool transit = false); //dst must be free, neighbouring tile (this function can move hero only by one tile)
|
||||
bool moveHero(const CGHeroInstance *h, int3 dst, bool transit = false) override; //dst must be free, neighbouring tile (this function can move hero only by one tile)
|
||||
bool teleportHero(const CGHeroInstance *who, const CGTownInstance *where);
|
||||
int selectionMade(int selection, QueryID queryID);
|
||||
int swapCreatures(const CArmedInstance *s1, const CArmedInstance *s2, SlotID p1, SlotID p2);
|
||||
int mergeOrSwapStacks(const CArmedInstance *s1, const CArmedInstance *s2, SlotID p1, SlotID p2); //first goes to the second
|
||||
int mergeStacks(const CArmedInstance *s1, const CArmedInstance *s2, SlotID p1, SlotID p2); //first goes to the second
|
||||
int splitStack(const CArmedInstance *s1, const CArmedInstance *s2, SlotID p1, SlotID p2, int val);
|
||||
bool dismissHero(const CGHeroInstance * hero);
|
||||
int selectionMade(int selection, QueryID queryID) override;
|
||||
int swapCreatures(const CArmedInstance *s1, const CArmedInstance *s2, SlotID p1, SlotID p2) override;
|
||||
int mergeOrSwapStacks(const CArmedInstance *s1, const CArmedInstance *s2, SlotID p1, SlotID p2) override; //first goes to the second
|
||||
int mergeStacks(const CArmedInstance *s1, const CArmedInstance *s2, SlotID p1, SlotID p2) override; //first goes to the second
|
||||
int splitStack(const CArmedInstance *s1, const CArmedInstance *s2, SlotID p1, SlotID p2, int val) override;
|
||||
bool dismissHero(const CGHeroInstance * hero) override;
|
||||
//bool swapArtifacts(const CGHeroInstance * hero1, ui16 pos1, const CGHeroInstance * hero2, ui16 pos2);
|
||||
bool swapArtifacts(const ArtifactLocation &l1, const ArtifactLocation &l2);
|
||||
bool swapArtifacts(const ArtifactLocation &l1, const ArtifactLocation &l2) override;
|
||||
//bool moveArtifact(const CGHeroInstance * hero, ui16 src, const CStackInstance * stack, ui16 dest); // TODO: unify classes
|
||||
//bool moveArtifact(const CStackInstance * stack, ui16 src , const CGHeroInstance * hero, ui16 dest); // TODO: unify classes
|
||||
bool assembleArtifacts(const CGHeroInstance * hero, ArtifactPosition artifactSlot, bool assemble, ArtifactID assembleTo);
|
||||
bool assembleArtifacts(const CGHeroInstance * hero, ArtifactPosition artifactSlot, bool assemble, ArtifactID assembleTo) override;
|
||||
bool buildBuilding(const CGTownInstance *town, BuildingID buildingID) override;
|
||||
void recruitCreatures(const CGDwelling * obj, const CArmedInstance * dst, CreatureID ID, ui32 amount, si32 level=-1);
|
||||
bool dismissCreature(const CArmedInstance *obj, SlotID stackPos);
|
||||
void recruitCreatures(const CGDwelling * obj, const CArmedInstance * dst, CreatureID ID, ui32 amount, si32 level=-1) override;
|
||||
bool dismissCreature(const CArmedInstance *obj, SlotID stackPos) override;
|
||||
bool upgradeCreature(const CArmedInstance *obj, SlotID stackPos, CreatureID newID=CreatureID::NONE) override;
|
||||
void endTurn();
|
||||
void swapGarrisonHero(const CGTownInstance *town);
|
||||
void endTurn() override;
|
||||
void swapGarrisonHero(const CGTownInstance *town) override;
|
||||
void buyArtifact(const CGHeroInstance *hero, ArtifactID aid) override;
|
||||
void trade(const CGObjectInstance *market, EMarketMode::EMarketMode mode, int id1, int id2, int val1, const CGHeroInstance *hero = nullptr);
|
||||
void setFormation(const CGHeroInstance * hero, bool tight);
|
||||
void recruitHero(const CGObjectInstance *townOrTavern, const CGHeroInstance *hero);
|
||||
void save(const std::string &fname);
|
||||
void sendMessage(const std::string &mess, const CGObjectInstance * currentObject = nullptr);
|
||||
void buildBoat(const IShipyard *obj);
|
||||
void dig(const CGObjectInstance *hero);
|
||||
void castSpell(const CGHeroInstance *hero, SpellID spellID, const int3 &pos = int3(-1, -1, -1));
|
||||
void trade(const CGObjectInstance *market, EMarketMode::EMarketMode mode, int id1, int id2, int val1, const CGHeroInstance *hero = nullptr) override;
|
||||
void setFormation(const CGHeroInstance * hero, bool tight) override;
|
||||
void recruitHero(const CGObjectInstance *townOrTavern, const CGHeroInstance *hero) override;
|
||||
void save(const std::string &fname) override;
|
||||
void sendMessage(const std::string &mess, const CGObjectInstance * currentObject = nullptr) override;
|
||||
void buildBoat(const IShipyard *obj) override;
|
||||
void dig(const CGObjectInstance *hero) override;
|
||||
void castSpell(const CGHeroInstance *hero, SpellID spellID, const int3 &pos = int3(-1, -1, -1)) override;
|
||||
|
||||
//friends
|
||||
friend class CClient;
|
||||
|
@ -13,15 +13,20 @@ endif()
|
||||
|
||||
# VCMI version
|
||||
set(VCMI_VERSION_MAJOR 0)
|
||||
set(VCMI_VERSION_MINOR 98)
|
||||
set(VCMI_VERSION_MINOR 99)
|
||||
set(VCMI_VERSION_PATCH 0)
|
||||
|
||||
option(ENABLE_ERM "Enable compilation of ERM scripting module" OFF)
|
||||
option(ENABLE_EDITOR "Enable compilation of map editor" OFF)
|
||||
option(ENABLE_LAUNCHER "Enable compilation of launcher" ON)
|
||||
option(ENABLE_TEST "Enable compilation of unit tests" OFF)
|
||||
option(ENABLE_TEST "Enable compilation of unit tests" ON)
|
||||
option(ENABLE_PCH "Enable compilation using precompiled headers" ON)
|
||||
option(ENABLE_SDL2 "Use SDL2 for compilation instead of SDL 1.2" ON)
|
||||
|
||||
############################################
|
||||
# Documentation section #
|
||||
############################################
|
||||
|
||||
include(UseDoxygen OPTIONAL)
|
||||
|
||||
############################################
|
||||
# Building section #
|
||||
@ -59,7 +64,7 @@ endif()
|
||||
if (WIN32)
|
||||
add_definitions(-DBOOST_THREAD_USE_LIB)
|
||||
add_definitions(-D_WIN32_WINNT=0x0501)
|
||||
set(SYSTEM_LIBS ${SYSTEM_LIBS} ole32 oleaut32 ws2_32 mswsock)
|
||||
set(SYSTEM_LIBS ${SYSTEM_LIBS} ole32 oleaut32 ws2_32 mswsock dbghelp)
|
||||
|
||||
#delete lib prefix for dlls (libvcmi -> vcmi)
|
||||
set(CMAKE_SHARED_LIBRARY_PREFIX "")
|
||||
@ -110,7 +115,7 @@ endif()
|
||||
set(SYSTEM_LIBS ${SYSTEM_LIBS} ${CMAKE_DL_LIBS})
|
||||
|
||||
set(FFmpeg_FIND_COMPONENTS AVFORMAT SWSCALE)
|
||||
find_package(Boost 1.48.0 COMPONENTS filesystem locale program_options system thread REQUIRED)
|
||||
find_package(Boost 1.48.0 COMPONENTS date_time filesystem locale program_options system thread REQUIRED)
|
||||
find_package(ZLIB REQUIRED)
|
||||
find_package(FFmpeg REQUIRED)
|
||||
find_package(Minizip)
|
||||
@ -118,26 +123,20 @@ if (MINIZIP_FOUND)
|
||||
add_definitions(-DUSE_SYSTEM_MINIZIP)
|
||||
endif()
|
||||
|
||||
if (ENABLE_SDL2)
|
||||
find_package(SDL2 REQUIRED)
|
||||
find_package(SDL2_image REQUIRED)
|
||||
find_package(SDL2_mixer REQUIRED)
|
||||
find_package(SDL2_ttf REQUIRED)
|
||||
find_package(SDL2 REQUIRED)
|
||||
find_package(SDL2_image REQUIRED)
|
||||
find_package(SDL2_mixer REQUIRED)
|
||||
find_package(SDL2_ttf REQUIRED)
|
||||
|
||||
set(SDL_INCLUDE_DIR "${SDL2_INCLUDE_DIR}")
|
||||
set(SDLTTF_INCLUDE_DIR "${SDL2_TTF_INCLUDE_DIR}")
|
||||
set(SDLIMAGE_INCLUDE_DIR "${SDL2_IMAGE_INCLUDE_DIR}")
|
||||
set(SDLMIXER_INCLUDE_DIR "${SDL2_MIXER_INCLUDE_DIR}")
|
||||
set(SDL_LIBRARY "${SDL2_LIBRARY}")
|
||||
set(SDLTTF_LIBRARY "${SDL2_TTF_LIBRARY}")
|
||||
set(SDLIMAGE_LIBRARY "${SDL2_IMAGE_LIBRARY}")
|
||||
set(SDLMIXER_LIBRARY "${SDL2_MIXER_LIBRARY}")
|
||||
|
||||
set(SDL_INCLUDE_DIR "${SDL2_INCLUDE_DIR}")
|
||||
set(SDLTTF_INCLUDE_DIR "${SDL2_TTF_INCLUDE_DIR}")
|
||||
set(SDLIMAGE_INCLUDE_DIR "${SDL2_IMAGE_INCLUDE_DIR}")
|
||||
set(SDLMIXER_INCLUDE_DIR "${SDL2_MIXER_INCLUDE_DIR}")
|
||||
set(SDL_LIBRARY "${SDL2_LIBRARY}")
|
||||
set(SDLTTF_LIBRARY "${SDL2_TTF_LIBRARY}")
|
||||
set(SDLIMAGE_LIBRARY "${SDL2_IMAGE_LIBRARY}")
|
||||
set(SDLMIXER_LIBRARY "${SDL2_MIXER_LIBRARY}")
|
||||
else()
|
||||
find_package(SDL REQUIRED)
|
||||
find_package(SDL_image REQUIRED)
|
||||
find_package(SDL_mixer REQUIRED)
|
||||
find_package(SDL_ttf REQUIRED)
|
||||
endif()
|
||||
include(cotire)
|
||||
|
||||
if (ENABLE_EDITOR OR ENABLE_LAUNCHER)
|
||||
@ -151,7 +150,7 @@ endif()
|
||||
|
||||
if(ENABLE_TEST)
|
||||
# find_package overwrites BOOST_* variables which are already set, so all components have to be included again
|
||||
find_package(Boost 1.48.0 COMPONENTS program_options filesystem system thread locale unit_test_framework REQUIRED)
|
||||
find_package(Boost 1.48.0 COMPONENTS date_time program_options filesystem system thread locale unit_test_framework REQUIRED)
|
||||
endif()
|
||||
|
||||
if(CMAKE_COMPILER_IS_GNUCXX OR NOT WIN32) #so far all *nix compilers support such parameters
|
||||
@ -236,7 +235,7 @@ endif()
|
||||
# Installation section #
|
||||
#######################################
|
||||
|
||||
# For apple this files will be already inside vcmiclient bundle
|
||||
# For apple these files will be already inside vcmiclient bundle
|
||||
if (NOT APPLE)
|
||||
# copy whole directory but .svn control files
|
||||
install(DIRECTORY config DESTINATION ${DATA_DIR} PATTERN ".svn" EXCLUDE)
|
||||
@ -343,3 +342,6 @@ endif()
|
||||
|
||||
INCLUDE(CPack)
|
||||
|
||||
include(GetGitRevisionDescription)
|
||||
get_git_head_revision(GIT_REFSPEC GIT_SHA1)
|
||||
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/Version.cpp.in" "${CMAKE_BINARY_DIR}/Version.cpp" @ONLY)
|
||||
|
29
ChangeLog
29
ChangeLog
@ -1,14 +1,39 @@
|
||||
0.98 -> 0.next
|
||||
0.98 -> 0.99
|
||||
|
||||
GENERAL:
|
||||
* New Bonus NO_TERRAIN_PENALTY
|
||||
* Nomads will remove Sand movement penalty from army
|
||||
* Flying and water walking is now supported in pathfinder
|
||||
* New artifacts supported
|
||||
- Angel Wings
|
||||
- Boots of Levitation
|
||||
* Implemented rumors in tavern window
|
||||
* New cheat codes:
|
||||
- vcmiglaurung - gives 5000 crystal dragons into each slot
|
||||
- vcmiungoliant - conceal fog of war for current player
|
||||
* New console commands:
|
||||
- gosolo - AI take control over human players and vice versa
|
||||
- controlai - give control of one or all AIs to player
|
||||
- set hideSystemMessages on/off - supress server messages in chat
|
||||
|
||||
BATTLES:
|
||||
* Drawbridge mechanics implemented (animation still missing)
|
||||
* Merging of town and visiting hero armies on siege implemented
|
||||
* Hero info tooltip for skills and mana implemented
|
||||
|
||||
ADVETURE AI:
|
||||
* Fixed AI trying to go through underground rock
|
||||
* Fixed several cases causing AI wandering aimlessly
|
||||
* AI can again pick bets artifacts and exchange artifacts between heroes
|
||||
* AI can again pick best artifacts and exchange artifacts between heroes
|
||||
* AI heroes with patrol enabled won't leave patrol area anymore
|
||||
|
||||
RANDOM MAP GENERATOR:
|
||||
* Changed fractalization algorithm so it can create cycles
|
||||
* Zones will not have straight paths anymore, they are totally random
|
||||
* Generated zones will have different size depending on template setting
|
||||
* Added Thieves Guild random object (1 per zone)
|
||||
* Added Seer Huts with quests that match OH3
|
||||
* RMG will guarantee at least 100 pairs of Monoliths are available even if there are not enough different defs
|
||||
|
||||
0.97 -> 0.98
|
||||
GENERAL:
|
||||
|
56
Global.h
56
Global.h
@ -55,13 +55,13 @@ static_assert(sizeof(bool) == 1, "Bool needs to be 1 byte in size.");
|
||||
# define VCMI_UNIX
|
||||
# define VCMI_XDG
|
||||
# ifdef __ANDROID__
|
||||
# define VCMI_ANDROID
|
||||
# define VCMI_ANDROID
|
||||
# endif
|
||||
#elif defined(__FreeBSD_kernel__) || defined(__FreeBSD__)
|
||||
# define VCMI_UNIX
|
||||
# define VCMI_XDG
|
||||
# define VCMI_FREEBSD
|
||||
#elif defined(__GNU__) || defined(__gnu_hurd__) || (defined(__MACH__) && !defined(__APPLE))
|
||||
#elif defined(__GNU__) || defined(__gnu_hurd__) || (defined(__MACH__) && !defined(__APPLE__))
|
||||
# define VCMI_UNIX
|
||||
# define VCMI_XDG
|
||||
# define VCMI_HURD
|
||||
@ -93,8 +93,25 @@ static_assert(sizeof(bool) == 1, "Bool needs to be 1 byte in size.");
|
||||
#ifdef VCMI_WINDOWS
|
||||
# define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers - delete this line if something is missing.
|
||||
# define NOMINMAX // Exclude min/max macros from <Windows.h>. Use std::[min/max] from <algorithm> instead.
|
||||
# define _NO_W32_PSEUDO_MODIFIERS // Exclude more macros for compiling with MinGW on Linux.
|
||||
#endif
|
||||
|
||||
/* ---------------------------------------------------------------------------- */
|
||||
/* A macro to force inlining some of our functions */
|
||||
/* ---------------------------------------------------------------------------- */
|
||||
// Compiler (at least MSVC) is not so smart here-> without that displaying is MUCH slower
|
||||
#ifdef _MSC_VER
|
||||
# define STRONG_INLINE __forceinline
|
||||
#elif __GNUC__
|
||||
# define STRONG_INLINE inline __attribute__((always_inline))
|
||||
#else
|
||||
# define STRONG_INLINE inline
|
||||
#endif
|
||||
|
||||
#define TO_STRING_HELPER(x) #x
|
||||
#define TO_STRING(x) TO_STRING_HELPER(x)
|
||||
#define LINE_IN_FILE __FILE__ ":" TO_STRING(__LINE__)
|
||||
|
||||
#define _USE_MATH_DEFINES
|
||||
|
||||
#include <cstdio>
|
||||
@ -133,6 +150,10 @@ static_assert(sizeof(bool) == 1, "Bool needs to be 1 byte in size.");
|
||||
#define BOOST_THREAD_DONT_PROVIDE_THREAD_DESTRUCTOR_CALLS_TERMINATE_IF_JOINABLE 1
|
||||
#define BOOST_BIND_NO_PLACEHOLDERS
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER == 1900)
|
||||
#define BOOST_NO_CXX11_VARIADIC_TEMPLATES //Variadic templates are buggy in VS2015, so turn this off to avoid compile errors
|
||||
#endif
|
||||
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include <boost/cstdint.hpp>
|
||||
#include <boost/current_function.hpp>
|
||||
@ -150,6 +171,7 @@ static_assert(sizeof(bool) == 1, "Bool needs to be 1 byte in size.");
|
||||
#endif
|
||||
#include <boost/logic/tribool.hpp>
|
||||
#include <boost/optional.hpp>
|
||||
#include <boost/optional/optional_io.hpp>
|
||||
#include <boost/program_options.hpp>
|
||||
#include <boost/range/adaptor/filtered.hpp>
|
||||
#include <boost/range/adaptor/reversed.hpp>
|
||||
@ -157,6 +179,7 @@ static_assert(sizeof(bool) == 1, "Bool needs to be 1 byte in size.");
|
||||
#include <boost/thread.hpp>
|
||||
#include <boost/variant.hpp>
|
||||
#include <boost/math/special_functions/round.hpp>
|
||||
#include <boost/multi_array.hpp>
|
||||
|
||||
#ifndef M_PI
|
||||
# define M_PI 3.14159265358979323846
|
||||
@ -165,9 +188,6 @@ static_assert(sizeof(bool) == 1, "Bool needs to be 1 byte in size.");
|
||||
/* ---------------------------------------------------------------------------- */
|
||||
/* Usings */
|
||||
/* ---------------------------------------------------------------------------- */
|
||||
using std::shared_ptr;
|
||||
using std::unique_ptr;
|
||||
using std::make_shared;
|
||||
using namespace std::placeholders;
|
||||
namespace range = boost::range;
|
||||
|
||||
@ -206,7 +226,6 @@ typedef boost::lock_guard<boost::recursive_mutex> TLockGuardRec;
|
||||
# define DLL_IMPORT __attribute__ ((visibility("default")))
|
||||
# define DLL_EXPORT __attribute__ ((visibility("default")))
|
||||
# define ELF_VISIBILITY __attribute__ ((visibility("default")))
|
||||
# define ELF_VISIBILITY __attribute__ ((visibility("default")))
|
||||
# endif
|
||||
#endif
|
||||
|
||||
@ -230,7 +249,8 @@ template<typename T, size_t N> char (&_ArrayCountObj(const T (&)[N]))[N];
|
||||
/* ---------------------------------------------------------------------------- */
|
||||
/* VCMI standard library */
|
||||
/* ---------------------------------------------------------------------------- */
|
||||
#include "lib/logging/CLogger.h"
|
||||
#include <vstd/CLoggerBase.h>
|
||||
#include "lib/logging/CLogger.h" //todo: remove
|
||||
|
||||
void inline handleException()
|
||||
{
|
||||
@ -240,15 +260,15 @@ void inline handleException()
|
||||
}
|
||||
catch(const std::exception & ex)
|
||||
{
|
||||
logGlobal->errorStream() << ex.what();
|
||||
logGlobal->error(ex.what());
|
||||
}
|
||||
catch(const std::string & ex)
|
||||
{
|
||||
logGlobal->errorStream() << ex;
|
||||
logGlobal->error(ex);
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
logGlobal->errorStream() << "Sorry, caught unknown exception type. No more info available.";
|
||||
logGlobal->error("Sorry, caught unknown exception type. No more info available.");
|
||||
}
|
||||
}
|
||||
|
||||
@ -273,7 +293,7 @@ std::ostream & operator<<(std::ostream & out, const std::vector<T> & container)
|
||||
|
||||
namespace vstd
|
||||
{
|
||||
|
||||
|
||||
// combine hashes. Present in boost but not in std
|
||||
template <class T>
|
||||
inline void hash_combine(std::size_t& seed, const T& v)
|
||||
@ -281,7 +301,7 @@ namespace vstd
|
||||
std::hash<T> hasher;
|
||||
seed ^= hasher(v) + 0x9e3779b9 + (seed<<6) + (seed>>2);
|
||||
}
|
||||
|
||||
|
||||
//returns true if container c contains item i
|
||||
template <typename Container, typename Item>
|
||||
bool contains(const Container & c, const Item &i)
|
||||
@ -493,7 +513,7 @@ namespace vstd
|
||||
void erase_if(std::set<Elem> &setContainer, Predicate pred)
|
||||
{
|
||||
auto itr = setContainer.begin();
|
||||
auto endItr = setContainer.end();
|
||||
auto endItr = setContainer.end();
|
||||
while(itr != endItr)
|
||||
{
|
||||
auto tmpItr = itr++;
|
||||
@ -507,7 +527,7 @@ namespace vstd
|
||||
void erase_if(std::map<Key, Val> &container, Predicate pred)
|
||||
{
|
||||
auto itr = container.begin();
|
||||
auto endItr = container.end();
|
||||
auto endItr = container.end();
|
||||
while(itr != endItr)
|
||||
{
|
||||
auto tmpItr = itr++;
|
||||
@ -542,7 +562,7 @@ namespace vstd
|
||||
return vf(lhs) < vf(rhs);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
//Returns iterator to the element for which the value of ValueFunction is maximal
|
||||
template<class ForwardRange, class ValueFunction>
|
||||
auto maxElementByFun(const ForwardRange& rng, ValueFunction vf) -> decltype(std::begin(rng))
|
||||
@ -615,7 +635,7 @@ namespace vstd
|
||||
{
|
||||
if(index < r.size())
|
||||
return r[index];
|
||||
|
||||
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
@ -656,12 +676,12 @@ namespace vstd
|
||||
boost::sort(vec);
|
||||
vec.erase(std::unique(vec.begin(), vec.end()), vec.end());
|
||||
}
|
||||
|
||||
|
||||
template <typename T>
|
||||
void concatenate(std::vector<T> &dest, const std::vector<T> &src)
|
||||
{
|
||||
dest.reserve(dest.size() + src.size());
|
||||
dest.insert(dest.end(), src.begin(), src.end());
|
||||
dest.insert(dest.end(), src.begin(), src.end());
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
|
7
Mods/vcmi/Sprites/ScSelC.json
Normal file
7
Mods/vcmi/Sprites/ScSelC.json
Normal file
@ -0,0 +1,7 @@
|
||||
{
|
||||
"basepath" : "mapFormatIcons/",
|
||||
"images" :
|
||||
[
|
||||
{ "group" : 1, "frame" : 0, "file" : "vcmi1.png"}
|
||||
]
|
||||
}
|
BIN
Mods/vcmi/Sprites/mapFormatIcons/vcmi1.png
Normal file
BIN
Mods/vcmi/Sprites/mapFormatIcons/vcmi1.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.0 KiB |
21
README.linux
21
README.linux
@ -20,7 +20,7 @@ To compile, the following packages (and their development counterparts) are need
|
||||
* zlib and zlib-devel
|
||||
* (optional) Qt 5, widget and network modules
|
||||
* the ffmpeg libraries (libavformat and libswscale). Their name could be libavformat-devel and libswscale-devel, or ffmpeg-libs-devel or similar names.
|
||||
* boost c++ libraries v1.48+ (www.boost.org):
|
||||
* boost c++ libraries v1.50+ (www.boost.org):
|
||||
- program-options
|
||||
- filesystem
|
||||
- system
|
||||
@ -28,11 +28,17 @@ To compile, the following packages (and their development counterparts) are need
|
||||
- locale
|
||||
|
||||
On Debian-based systems (e.g. Ubuntu) run:
|
||||
sudo apt-get install cmake g++ libsdl1.2debian libsdl-image1.2-dev libsdl-ttf2.0-dev libsdl-mixer1.2-dev zlib1g-dev libavformat-dev libswscale-dev libboost-dev libboost-filesystem-dev libboost-system-dev libboost-thread-dev libboost-program-options-dev libboost-locale-dev qtbase5-dev
|
||||
sudo apt-get install cmake g++ libsdl2-dev libsdl2-image-dev libsdl2-ttf-dev libsdl2-mixer-dev zlib1g-dev libavformat-dev libswscale-dev libboost-dev libboost-filesystem-dev libboost-system-dev libboost-thread-dev libboost-program-options-dev libboost-locale-dev libboost-test-dev qtbase5-dev
|
||||
|
||||
On RPM-based distributions (e.g. Fedora) run:
|
||||
sudo yum install cmake gcc-c++ SDL2-devel SDL2_image-devel SDL2_ttf-devel SDL2_mixer-devel boost boost-devel boost-filesystem boost-system boost-thread boost-program-options boost-locale zlib-devel ffmpeg-devel ffmpeg-libs qt5-qtbase-devel
|
||||
|
||||
On Arch-based distributions, there is a development package available for VCMI on the AUR. It can be found at:
|
||||
https://aur.archlinux.org/packages/vcmi-git/
|
||||
|
||||
Information about building packages from the Arch User Repository (AUR) can be
|
||||
found at the Arch wiki.
|
||||
|
||||
II. Getting the sources
|
||||
|
||||
VCMI is still in development. We recommend the following initial directory structure:
|
||||
@ -93,3 +99,14 @@ Go to /LIB_PATH/vcmi/AI, and type:
|
||||
Go to /DATA_PATH/vcmi, and type:
|
||||
ln -s .../trunk/source/config
|
||||
ln -s .../trunk/source/Mods
|
||||
|
||||
IV. Compiling documentation
|
||||
|
||||
To compile using Doxygen, the UseDoxygen CMake module must be installed. It can
|
||||
be fetched from: http://tobias.rautenkranz.ch/cmake/doxygen/
|
||||
|
||||
Once UseDoxygen is installed, run:
|
||||
cmake .
|
||||
make doc
|
||||
|
||||
The built documentation will be available from ./doc
|
||||
|
@ -1,3 +1,4 @@
|
||||
[![Build Status](https://travis-ci.org/vcmi/vcmi.svg?branch=develop)](https://travis-ci.org/vcmi/vcmi)
|
||||
# VCMI Project
|
||||
VCMI is work-in-progress attempt to recreate engine for Heroes III, giving it new and extended possibilities. To use VCMI you need to own original data files.
|
||||
|
||||
@ -18,4 +19,4 @@ For building from source see project wiki at http://wiki.vcmi.eu/
|
||||
VCMI Project source code is licensed under GPL version 2 or later.
|
||||
VCMI Project assets are licensed under CC-BY-SA 4.0. Assets sources and information about contributors are available under following link: [https://github.com/vcmi/vcmi-assets]
|
||||
|
||||
Copyright (C) 2007-2015 VCMI Team (check AUTHORS file for the contributors list)
|
||||
Copyright (C) 2007-2016 VCMI Team (check AUTHORS file for the contributors list)
|
||||
|
@ -7,7 +7,7 @@
|
||||
<PropertyGroup>
|
||||
<_PropertySheetDisplayName>VCMI_global</_PropertySheetDisplayName>
|
||||
<LibraryPath>$(SolutionDir)..\libs\$(PlatformShortName);$(VCMI_Out);$(LibraryPath)</LibraryPath>
|
||||
<IncludePath>$(SolutionDir)..\include;$(IncludePath)</IncludePath>
|
||||
<IncludePath>$(SolutionDir)..\include;$(SolutionDir)include;$(IncludePath)</IncludePath>
|
||||
<OutDir>$(VCMI_Out)\</OutDir>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup>
|
||||
|
6
Version.cpp.in
Normal file
6
Version.cpp.in
Normal file
@ -0,0 +1,6 @@
|
||||
#include "Version.h"
|
||||
|
||||
namespace GameConstants
|
||||
{
|
||||
const char GIT_SHA1[] = "@GIT_SHA1@";
|
||||
}
|
4
Version.h
Normal file
4
Version.h
Normal file
@ -0,0 +1,4 @@
|
||||
namespace GameConstants
|
||||
{
|
||||
extern const char GIT_SHA1[];
|
||||
}
|
@ -1,11 +1,9 @@
|
||||
#include "StdInc.h"
|
||||
|
||||
#include "../lib/filesystem/Filesystem.h"
|
||||
#include "../lib/filesystem/CFileInfo.h"
|
||||
#include "SDL.h"
|
||||
#include "SDL_image.h"
|
||||
#include "CBitmapHandler.h"
|
||||
#include "CDefHandler.h"
|
||||
#include "gui/SDL_Extensions.h"
|
||||
#include "../lib/vcmi_endian.h"
|
||||
|
||||
@ -19,6 +17,14 @@
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
namespace BitmapHandler
|
||||
{
|
||||
SDL_Surface * loadH3PCX(ui8 * data, size_t size);
|
||||
|
||||
SDL_Surface * loadBitmapFromDir(std::string path, std::string fname, bool setKey=true);
|
||||
}
|
||||
|
||||
bool isPCX(const ui8 *header)//check whether file can be PCX according to header
|
||||
{
|
||||
int fSize = read_le_u32(header + 0);
|
||||
@ -70,7 +76,7 @@ SDL_Surface * BitmapHandler::loadH3PCX(ui8 * pcx, size_t size)
|
||||
tp.r = pcx[it++];
|
||||
tp.g = pcx[it++];
|
||||
tp.b = pcx[it++];
|
||||
CSDL_Ext::colorSetAlpha(tp,SDL_ALPHA_OPAQUE);
|
||||
tp.a = SDL_ALPHA_OPAQUE;
|
||||
ret->format->palette->colors[i] = tp;
|
||||
}
|
||||
}
|
||||
@ -102,7 +108,7 @@ SDL_Surface * BitmapHandler::loadBitmapFromDir(std::string path, std::string fna
|
||||
{
|
||||
if(!fname.size())
|
||||
{
|
||||
logGlobal->warnStream() << "Call to loadBitmap with void fname!";
|
||||
logGlobal->warnStream() << "Call to loadBitmap with void fname!";
|
||||
return nullptr;
|
||||
}
|
||||
if (!CResourceHandler::get()->existsResource(ResourceID(path + fname, EResType::IMAGE)))
|
||||
@ -142,13 +148,13 @@ SDL_Surface * BitmapHandler::loadBitmapFromDir(std::string path, std::string fna
|
||||
{
|
||||
//set correct value for alpha\unused channel
|
||||
for (int i=0; i < ret->format->palette->ncolors; i++)
|
||||
CSDL_Ext::colorSetAlpha(ret->format->palette->colors[i],SDL_ALPHA_OPAQUE);
|
||||
ret->format->palette->colors[i].a = SDL_ALPHA_OPAQUE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
logGlobal->errorStream()<<"Failed to open "<<fname<<" via SDL_Image";
|
||||
logGlobal->errorStream()<<"Reason: " << IMG_GetError();
|
||||
logGlobal->errorStream() << "Failed to open " << fname << " via SDL_Image";
|
||||
logGlobal->errorStream() << "Reason: " << IMG_GetError();
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
@ -174,7 +180,9 @@ SDL_Surface * BitmapHandler::loadBitmap(std::string fname, bool setKey)
|
||||
|
||||
if (!(bitmap = loadBitmapFromDir("DATA/", fname, setKey)) &&
|
||||
!(bitmap = loadBitmapFromDir("SPRITES/", fname, setKey)))
|
||||
logGlobal->errorStream()<<"Error: Failed to find file "<<fname;
|
||||
{
|
||||
logGlobal->errorStream() << "Error: Failed to find file " << fname;
|
||||
}
|
||||
|
||||
return bitmap;
|
||||
}
|
||||
|
@ -14,9 +14,6 @@ struct SDL_Surface;
|
||||
|
||||
namespace BitmapHandler
|
||||
{
|
||||
SDL_Surface * loadH3PCX(ui8 * data, size_t size);
|
||||
//Load file from specific LOD
|
||||
SDL_Surface * loadBitmapFromDir(std::string path, std::string fname, bool setKey=true);
|
||||
//Load file from any LODs
|
||||
//Load file from /DATA or /SPRITES
|
||||
SDL_Surface * loadBitmap(std::string fname, bool setKey=true);
|
||||
}
|
||||
|
@ -67,7 +67,7 @@ void CDefHandler::openFromMemory(ui8 *table, const std::string & name)
|
||||
palette[it].r = de.palette[it].R;
|
||||
palette[it].g = de.palette[it].G;
|
||||
palette[it].b = de.palette[it].B;
|
||||
CSDL_Ext::colorSetAlpha(palette[it],SDL_ALPHA_OPAQUE);
|
||||
palette[it].a = SDL_ALPHA_OPAQUE;
|
||||
}
|
||||
|
||||
// The SDefEntryBlock starts just after the SDefEntry
|
||||
@ -122,12 +122,6 @@ void CDefHandler::openFromMemory(ui8 *table, const std::string & name)
|
||||
}
|
||||
}
|
||||
|
||||
void CDefHandler::expand(ui8 N,ui8 & BL, ui8 & BR)
|
||||
{
|
||||
BL = (N & 0xE0) >> 5;
|
||||
BR = N & 0x1F;
|
||||
}
|
||||
|
||||
SDL_Surface * CDefHandler::getSprite (int SIndex, const ui8 * FDef, const SDL_Color * palette) const
|
||||
{
|
||||
SDL_Surface * ret=nullptr;
|
||||
@ -180,24 +174,11 @@ SDL_Surface * CDefHandler::getSprite (int SIndex, const ui8 * FDef, const SDL_Co
|
||||
|
||||
BaseOffset += sizeof(SSpriteDef);
|
||||
int BaseOffsetor = BaseOffset;
|
||||
|
||||
#ifdef VCMI_SDL1
|
||||
for(int i=0; i<256; ++i)
|
||||
{
|
||||
SDL_Color pr;
|
||||
pr.r = palette[i].r;
|
||||
pr.g = palette[i].g;
|
||||
pr.b = palette[i].b;
|
||||
pr.unused = palette[i].unused;
|
||||
(*(ret->format->palette->colors+i))=pr;
|
||||
}
|
||||
#else
|
||||
if(SDL_SetPaletteColors(ret->format->palette,palette,0,256) != 0)
|
||||
{
|
||||
throw std::runtime_error("Unable to set palette");
|
||||
}
|
||||
|
||||
#endif
|
||||
SDL_Palette * p = SDL_AllocPalette(256);
|
||||
SDL_SetPaletteColors(p, palette, 0, 256);
|
||||
SDL_SetSurfacePalette(ret, p);
|
||||
SDL_FreePalette(p);
|
||||
|
||||
int ftcp=0;
|
||||
|
||||
@ -363,13 +344,8 @@ SDL_Surface * CDefHandler::getSprite (int SIndex, const ui8 * FDef, const SDL_Co
|
||||
}
|
||||
|
||||
SDL_Color ttcol = ret->format->palette->colors[0];
|
||||
#ifdef VCMI_SDL1
|
||||
Uint32 keycol = SDL_MapRGBA(ret->format, ttcol.r, ttcol.b, ttcol.g, ttcol.unused);
|
||||
SDL_SetColorKey(ret, SDL_SRCCOLORKEY, keycol);
|
||||
#else
|
||||
Uint32 keycol = SDL_MapRGBA(ret->format, ttcol.r, ttcol.b, ttcol.g, ttcol.a);
|
||||
SDL_SetColorKey(ret, SDL_TRUE, keycol);
|
||||
#endif // 0
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -85,7 +85,9 @@ private:
|
||||
int group;
|
||||
} ;
|
||||
std::vector<SEntry> SEntries ;
|
||||
|
||||
|
||||
void openFromMemory(ui8 * table, const std::string & name);
|
||||
SDL_Surface * getSprite (int SIndex, const ui8 * FDef, const SDL_Color * palette) const;
|
||||
public:
|
||||
int width, height; //width and height
|
||||
std::string defName;
|
||||
@ -94,9 +96,7 @@ public:
|
||||
|
||||
CDefHandler(); //c-tor
|
||||
~CDefHandler(); //d-tor
|
||||
SDL_Surface * getSprite (int SIndex, const ui8 * FDef, const SDL_Color * palette) const; //saves picture with given number to "testtt.bmp"
|
||||
static void expand(ui8 N,ui8 & BL, ui8 & BR);
|
||||
void openFromMemory(ui8 * table, const std::string & name);
|
||||
|
||||
CDefEssential * essentialize();
|
||||
|
||||
static CDefHandler * giveDef(const std::string & defName);
|
||||
|
610
client/CMT.cpp
610
client/CMT.cpp
File diff suppressed because it is too large
Load Diff
@ -1,6 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef VCMI_SDL1
|
||||
#include <SDL_render.h>
|
||||
|
||||
extern SDL_Texture * screenTexture;
|
||||
@ -8,8 +7,6 @@ extern SDL_Texture * screenTexture;
|
||||
extern SDL_Window * mainWindow;
|
||||
extern SDL_Renderer * mainRenderer;
|
||||
|
||||
#endif // VCMI_SDL2
|
||||
|
||||
extern SDL_Surface *screen; // main screen surface
|
||||
extern SDL_Surface *screen2; // and hlp surface (used to store not-active interfaces layer)
|
||||
extern SDL_Surface *screenBuf; // points to screen (if only advmapint is present) or screen2 (else) - should be used when updating controls which are not regularly redrawed
|
||||
@ -17,4 +14,4 @@ extern SDL_Surface *screenBuf; // points to screen (if only advmapint is present
|
||||
|
||||
extern bool gNoGUI; //if true there is no client window and game is silently played between AIs
|
||||
|
||||
void handleQuit();
|
||||
void handleQuit(bool ask = true);
|
||||
|
@ -1,7 +1,7 @@
|
||||
project(vcmiclient)
|
||||
cmake_minimum_required(VERSION 2.6)
|
||||
|
||||
include_directories(${CMAKE_HOME_DIRECTORY} ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_HOME_DIRECTORY}/lib)
|
||||
include_directories(${CMAKE_HOME_DIRECTORY} ${CMAKE_HOME_DIRECTORY}/include ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_HOME_DIRECTORY}/lib)
|
||||
include_directories(${SDL_INCLUDE_DIR} ${SDLIMAGE_INCLUDE_DIR} ${SDLMIXER_INCLUDE_DIR} ${SDLTTF_INCLUDE_DIR})
|
||||
include_directories(${Boost_INCLUDE_DIRS} ${ZLIB_INCLUDE_DIR} ${FFMPEG_INCLUDE_DIRS})
|
||||
|
||||
@ -57,6 +57,7 @@ set(client_SRCS
|
||||
Graphics.cpp
|
||||
mapHandler.cpp
|
||||
NetPacksClient.cpp
|
||||
SDLRWwrapper.cpp
|
||||
)
|
||||
|
||||
set(client_HEADERS
|
||||
@ -102,7 +103,7 @@ if(APPLE)
|
||||
cp -r ${CMAKE_HOME_DIRECTORY}/osx/vcmibuilder.app ${BUNDLE_PATH}/MacOS/vcmibuilder.app &&
|
||||
|
||||
# Copy frameworks
|
||||
cp -r ${CMAKE_HOME_DIRECTORY}/${CMAKE_FRAMEWORK_PATH} ${BUNDLE_PATH}/Frameworks/ &&
|
||||
sh -c 'cp -r ${CMAKE_HOME_DIRECTORY}/${CMAKE_FRAMEWORK_PATH} ${BUNDLE_PATH}/Frameworks/ || true' &&
|
||||
|
||||
# Copy vcmi data
|
||||
mkdir -p ${BUNDLE_PATH}/Data &&
|
||||
@ -110,9 +111,10 @@ if(APPLE)
|
||||
mkdir -p ${BUNDLE_PATH}/Data/launcher &&
|
||||
cp -r ${CMAKE_HOME_DIRECTORY}/config/ ${BUNDLE_PATH}/Data/config/ &&
|
||||
cp -r ${CMAKE_HOME_DIRECTORY}/Mods/vcmi/ ${BUNDLE_PATH}/Data/Mods/vcmi/ &&
|
||||
cp -r ${CMAKE_HOME_DIRECTORY}/Mods/WoG/ ${BUNDLE_PATH}/Data/Mods/WoG/ &&
|
||||
sh -c 'cp -r ${CMAKE_HOME_DIRECTORY}/Mods/WoG/ ${BUNDLE_PATH}/Data/Mods/WoG/ || echo "Download WoG mod from http://wiki.vcmi.eu/index.php?title=Mod_list" ' &&
|
||||
sh -c 'cp -r ${CMAKE_HOME_DIRECTORY}/Mods/hota/ ${BUNDLE_PATH}/Data/Mods/hota/ || echo "Download HOTA mod from http://wiki.vcmi.eu/index.php?title=Mod_list" ' &&
|
||||
cp -r ${CMAKE_HOME_DIRECTORY}/launcher/icons/ ${BUNDLE_PATH}/Data/launcher/icons/)
|
||||
|
||||
|
||||
add_custom_command(TARGET vcmiclient POST_BUILD COMMAND ${MakeVCMIBundle})
|
||||
elseif(WIN32)
|
||||
add_executable(vcmiclient ${client_SRCS} VCMI_client.rc)
|
||||
|
@ -15,7 +15,6 @@
|
||||
#include "CGameInfo.h"
|
||||
#include "gui/SDL_Extensions.h"
|
||||
#include "../lib/CGeneralTextHandler.h"
|
||||
#include "Graphics.h"
|
||||
#include "windows/GUIClasses.h"
|
||||
#include "../lib/CConfigHandler.h"
|
||||
#include "CBitmapHandler.h"
|
||||
@ -45,7 +44,7 @@ public:
|
||||
CComponent *comp;
|
||||
|
||||
//blit component with image centered at this position
|
||||
void showAll(SDL_Surface * to);
|
||||
void showAll(SDL_Surface * to) override;
|
||||
|
||||
//ComponentResolved(); //c-tor
|
||||
ComponentResolved(CComponent *Comp); //c-tor
|
||||
|
@ -3,6 +3,7 @@
|
||||
|
||||
#include "CMusicHandler.h"
|
||||
#include "CGameInfo.h"
|
||||
#include "SDLRWwrapper.h"
|
||||
#include "../lib/CCreatureHandler.h"
|
||||
#include "../lib/spells/CSpellHandler.h"
|
||||
#include "../lib/JsonNode.h"
|
||||
@ -51,7 +52,7 @@ void CAudioBase::init()
|
||||
|
||||
if (Mix_OpenAudio(44100, MIX_DEFAULT_FORMAT, 2, 1024)==-1)
|
||||
{
|
||||
logGlobal->errorStream() << "Mix_OpenAudio error: " << Mix_GetError();
|
||||
logGlobal->errorStream() << "Mix_OpenAudio error: " << Mix_GetError();
|
||||
return;
|
||||
}
|
||||
|
||||
@ -86,7 +87,7 @@ CSoundHandler::CSoundHandler():
|
||||
listener(std::bind(&CSoundHandler::onVolumeChange, this, _1));
|
||||
|
||||
// Vectors for helper(s)
|
||||
pickupSounds =
|
||||
pickupSounds =
|
||||
{
|
||||
soundBase::pickup01, soundBase::pickup02, soundBase::pickup03,
|
||||
soundBase::pickup04, soundBase::pickup05, soundBase::pickup06, soundBase::pickup07
|
||||
@ -127,8 +128,8 @@ void CSoundHandler::release()
|
||||
|
||||
for (auto &chunk : soundChunks)
|
||||
{
|
||||
if (chunk.second)
|
||||
Mix_FreeChunk(chunk.second);
|
||||
if (chunk.second.first)
|
||||
Mix_FreeChunk(chunk.second.first);
|
||||
}
|
||||
}
|
||||
|
||||
@ -141,20 +142,20 @@ Mix_Chunk *CSoundHandler::GetSoundChunk(std::string &sound, bool cache)
|
||||
try
|
||||
{
|
||||
if (cache && soundChunks.find(sound) != soundChunks.end())
|
||||
return soundChunks[sound];
|
||||
return soundChunks[sound].first;
|
||||
|
||||
auto data = CResourceHandler::get()->load(ResourceID(std::string("SOUNDS/") + sound, EResType::SOUND))->readAll();
|
||||
SDL_RWops *ops = SDL_RWFromMem(data.first.release(), data.second);
|
||||
SDL_RWops *ops = SDL_RWFromMem(data.first.get(), data.second);
|
||||
Mix_Chunk *chunk = Mix_LoadWAV_RW(ops, 1); // will free ops
|
||||
|
||||
if (cache)
|
||||
soundChunks.insert(std::pair<std::string, Mix_Chunk *>(sound, chunk));
|
||||
soundChunks.insert(std::pair<std::string, CachedChunk>(sound, std::make_pair (chunk, std::move (data.first))));
|
||||
|
||||
return chunk;
|
||||
}
|
||||
catch(std::exception &e)
|
||||
{
|
||||
logGlobal->warnStream() << "Cannot get sound " << sound << " chunk: " << e.what();
|
||||
logGlobal->warnStream() << "Cannot get sound " << sound << " chunk: " << e.what();
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
@ -182,7 +183,7 @@ int CSoundHandler::playSound(std::string sound, int repeats, bool cache)
|
||||
channel = Mix_PlayChannel(-1, chunk, repeats);
|
||||
if (channel == -1)
|
||||
{
|
||||
logGlobal->errorStream() << "Unable to play sound file " << sound << " , error " << Mix_GetError();
|
||||
logGlobal->errorStream() << "Unable to play sound file " << sound << " , error " << Mix_GetError();
|
||||
if (!cache)
|
||||
Mix_FreeChunk(chunk);
|
||||
}
|
||||
@ -303,7 +304,7 @@ void CMusicHandler::release()
|
||||
|
||||
void CMusicHandler::playMusic(std::string musicURI, bool loop)
|
||||
{
|
||||
if (current && current->isTrack( musicURI))
|
||||
if (current && current->isTrack(musicURI))
|
||||
return;
|
||||
|
||||
queueNext(this, "", musicURI, loop);
|
||||
@ -314,7 +315,7 @@ void CMusicHandler::playMusicFromSet(std::string whichSet, bool loop)
|
||||
auto selectedSet = musicsSet.find(whichSet);
|
||||
if (selectedSet == musicsSet.end())
|
||||
{
|
||||
logGlobal->errorStream() << "Error: playing music from non-existing set: " << whichSet;
|
||||
logGlobal->errorStream() << "Error: playing music from non-existing set: " << whichSet;
|
||||
return;
|
||||
}
|
||||
|
||||
@ -331,25 +332,25 @@ void CMusicHandler::playMusicFromSet(std::string whichSet, int entryID, bool loo
|
||||
auto selectedSet = musicsSet.find(whichSet);
|
||||
if (selectedSet == musicsSet.end())
|
||||
{
|
||||
logGlobal->errorStream() << "Error: playing music from non-existing set: " << whichSet;
|
||||
logGlobal->errorStream() << "Error: playing music from non-existing set: " << whichSet;
|
||||
return;
|
||||
}
|
||||
|
||||
auto selectedEntry = selectedSet->second.find(entryID);
|
||||
if (selectedEntry == selectedSet->second.end())
|
||||
{
|
||||
logGlobal->errorStream() << "Error: playing non-existing entry " << entryID << " from set: " << whichSet;
|
||||
logGlobal->errorStream() << "Error: playing non-existing entry " << entryID << " from set: " << whichSet;
|
||||
return;
|
||||
}
|
||||
|
||||
if (current && current->isTrack( selectedEntry->second))
|
||||
if (current && current->isTrack(selectedEntry->second))
|
||||
return;
|
||||
|
||||
// in this mode - play specific track from set
|
||||
queueNext(this, "", selectedEntry->second, loop);
|
||||
}
|
||||
|
||||
void CMusicHandler::queueNext(unique_ptr<MusicEntry> queued)
|
||||
void CMusicHandler::queueNext(std::unique_ptr<MusicEntry> queued)
|
||||
{
|
||||
if (!initialized)
|
||||
return;
|
||||
@ -421,12 +422,11 @@ void CMusicHandler::musicFinishedCallback(void)
|
||||
MusicEntry::MusicEntry(CMusicHandler *owner, std::string setName, std::string musicURI, bool looped):
|
||||
owner(owner),
|
||||
music(nullptr),
|
||||
musicFile(nullptr),
|
||||
loop(looped ? -1 : 1),
|
||||
setName(setName)
|
||||
setName(std::move(setName))
|
||||
{
|
||||
if (!musicURI.empty())
|
||||
load(musicURI);
|
||||
load(std::move(musicURI));
|
||||
}
|
||||
MusicEntry::~MusicEntry()
|
||||
{
|
||||
@ -448,33 +448,15 @@ void MusicEntry::load(std::string musicURI)
|
||||
|
||||
logGlobal->traceStream()<<"Loading music file "<<musicURI;
|
||||
|
||||
data = CResourceHandler::get()->load(ResourceID(musicURI, EResType::MUSIC))->readAll();
|
||||
musicFile = SDL_RWFromConstMem(data.first.get(), data.second);
|
||||
|
||||
#ifdef VCMI_SDL1
|
||||
music = Mix_LoadMUS_RW(musicFile);
|
||||
auto musicFile = MakeSDLRWops(CResourceHandler::get()->load(ResourceID(std::move(musicURI), EResType::MUSIC)));
|
||||
|
||||
music = Mix_LoadMUS_RW(musicFile, SDL_TRUE);
|
||||
|
||||
if(!music)
|
||||
{
|
||||
SDL_FreeRW(musicFile);
|
||||
musicFile = nullptr;
|
||||
logGlobal->warnStream() << "Warning: Cannot open " << currentName << ": " << Mix_GetError();
|
||||
return;
|
||||
}
|
||||
|
||||
#else
|
||||
music = Mix_LoadMUS_RW(musicFile, SDL_FALSE);
|
||||
|
||||
if(!music)
|
||||
{
|
||||
SDL_FreeRW(musicFile);
|
||||
musicFile = nullptr;
|
||||
logGlobal->warnStream() << "Warning: Cannot open " << currentName << ": " << Mix_GetError();
|
||||
return;
|
||||
}
|
||||
|
||||
#endif // 0
|
||||
|
||||
}
|
||||
|
||||
bool MusicEntry::play()
|
||||
@ -488,10 +470,10 @@ bool MusicEntry::play()
|
||||
load(RandomGeneratorUtil::nextItem(set, CRandomGenerator::getDefault())->second);
|
||||
}
|
||||
|
||||
logGlobal->traceStream()<<"Playing music file "<<currentName;
|
||||
logGlobal->traceStream()<<"Playing music file "<<currentName;
|
||||
if(Mix_PlayMusic(music, 1) == -1)
|
||||
{
|
||||
logGlobal->errorStream() << "Unable to play music (" << Mix_GetError() << ")";
|
||||
logGlobal->errorStream() << "Unable to play music (" << Mix_GetError() << ")";
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@ -501,7 +483,7 @@ bool MusicEntry::stop(int fade_ms)
|
||||
{
|
||||
if (Mix_PlayingMusic())
|
||||
{
|
||||
logGlobal->traceStream()<<"Stoping music file "<<currentName;
|
||||
logGlobal->traceStream()<<"Stoping music file "<<currentName;
|
||||
loop = 0;
|
||||
Mix_FadeOutMusic(fade_ms);
|
||||
return true;
|
||||
|
@ -41,7 +41,8 @@ private:
|
||||
SettingsListener listener;
|
||||
void onVolumeChange(const JsonNode &volumeNode);
|
||||
|
||||
std::map<std::string, Mix_Chunk *> soundChunks;
|
||||
using CachedChunk = std::pair<Mix_Chunk *, std::unique_ptr<ui8[]>>;
|
||||
std::map<std::string, CachedChunk> soundChunks;
|
||||
|
||||
Mix_Chunk *GetSoundChunk(std::string &sound, bool cache);
|
||||
|
||||
@ -52,10 +53,10 @@ private:
|
||||
public:
|
||||
CSoundHandler();
|
||||
|
||||
void init();
|
||||
void release();
|
||||
void init() override;
|
||||
void release() override;
|
||||
|
||||
void setVolume(ui32 percent);
|
||||
void setVolume(ui32 percent) override;
|
||||
|
||||
// Sounds
|
||||
int playSound(soundBase::soundID soundID, int repeats=0);
|
||||
@ -80,10 +81,8 @@ class CMusicHandler;
|
||||
//Class for handling one music file
|
||||
class MusicEntry
|
||||
{
|
||||
std::pair<std::unique_ptr<ui8[]>, size_t> data;
|
||||
CMusicHandler *owner;
|
||||
Mix_Music *music;
|
||||
SDL_RWops *musicFile;
|
||||
|
||||
int loop; // -1 = indefinite
|
||||
//if not null - set from which music will be randomly selected
|
||||
@ -114,11 +113,11 @@ private:
|
||||
SettingsListener listener;
|
||||
void onVolumeChange(const JsonNode &volumeNode);
|
||||
|
||||
unique_ptr<MusicEntry> current;
|
||||
unique_ptr<MusicEntry> next;
|
||||
|
||||
std::unique_ptr<MusicEntry> current;
|
||||
std::unique_ptr<MusicEntry> next;
|
||||
|
||||
void queueNext(CMusicHandler *owner, std::string setName, std::string musicURI, bool looped);
|
||||
void queueNext(unique_ptr<MusicEntry> queued);
|
||||
void queueNext(std::unique_ptr<MusicEntry> queued);
|
||||
|
||||
std::map<std::string, std::map<int, std::string> > musicsSet;
|
||||
public:
|
||||
@ -127,9 +126,9 @@ public:
|
||||
/// add entry with URI musicURI in set. Track will have ID musicID
|
||||
void addEntryToSet(std::string set, int musicID, std::string musicURI);
|
||||
|
||||
void init();
|
||||
void release();
|
||||
void setVolume(ui32 percent);
|
||||
void init() override;
|
||||
void release() override;
|
||||
void setVolume(ui32 percent) override;
|
||||
|
||||
/// play track by URI, if loop = true music will be looped
|
||||
void playMusic(std::string musicURI, bool loop);
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,12 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
|
||||
//#include "../lib/CondSh.h"
|
||||
#include "../lib/FunctionList.h"
|
||||
#include "../lib/CGameInterface.h"
|
||||
#include "../lib/NetPacksBase.h"
|
||||
#include "gui/CIntObject.h"
|
||||
//#include "../lib/CGameState.h"
|
||||
|
||||
#ifdef __GNUC__
|
||||
#define sprintf_s snprintf
|
||||
@ -29,12 +27,9 @@
|
||||
*
|
||||
*/
|
||||
|
||||
class CDefEssential;
|
||||
class CButton;
|
||||
class CToggleGroup;
|
||||
class CDefHandler;
|
||||
struct TryMoveHero;
|
||||
class CDefEssential;
|
||||
class CGHeroInstance;
|
||||
class CAdvMapInt;
|
||||
class CCastleInterface;
|
||||
@ -76,20 +71,22 @@ enum
|
||||
{
|
||||
/*CHANGE_SCREEN_RESOLUTION = 1,*/
|
||||
RETURN_TO_MAIN_MENU = 2,
|
||||
STOP_CLIENT = 3,
|
||||
RESTART_GAME,
|
||||
//STOP_CLIENT = 3,
|
||||
RESTART_GAME = 4,
|
||||
RETURN_TO_MENU_LOAD,
|
||||
FULLSCREEN_TOGGLED,
|
||||
PREPARE_RESTART_CAMPAIGN
|
||||
PREPARE_RESTART_CAMPAIGN,
|
||||
FORCE_QUIT //quit client without question
|
||||
};
|
||||
|
||||
/// Central class for managing user interface logic
|
||||
class CPlayerInterface : public CGameInterface, public ILockedUpdatable
|
||||
class CPlayerInterface : public CGameInterface, public IUpdateable
|
||||
{
|
||||
const CArmedInstance * currentSelection;
|
||||
public:
|
||||
bool observerInDuelMode;
|
||||
ObjectInstanceID destinationTeleport; //contain -1 or object id if teleportation
|
||||
int3 destinationTeleportPos;
|
||||
|
||||
//minor interfaces
|
||||
CondSh<bool> *showingDialog; //indicates if dialog box is displayed
|
||||
@ -105,7 +102,7 @@ public:
|
||||
static CBattleInterface * battleInt; //nullptr if no battle
|
||||
CInGameConsole * cingconsole;
|
||||
|
||||
shared_ptr<CCallback> cb; //to communicate with engine
|
||||
std::shared_ptr<CCallback> cb; //to communicate with engine
|
||||
const BattleAction *curAction; //during the battle - action currently performed by active stack (or nullptr)
|
||||
|
||||
std::list<CInfoWindow *> dialogs; //queue of dialogs awaiting to be shown (not currently shown!)
|
||||
@ -116,7 +113,7 @@ public:
|
||||
std::vector<const CGHeroInstance *> sleepingHeroes; //if hero is in here, he's sleeping
|
||||
|
||||
//During battle is quick combat mode is used
|
||||
shared_ptr<CBattleGameInterface> autofightingAI; //AI that makes decisions
|
||||
std::shared_ptr<CBattleGameInterface> autofightingAI; //AI that makes decisions
|
||||
bool isAutoFightOn; //Flag, switch it to stop quick combat. Don't touch if there is no battle interface.
|
||||
|
||||
const CArmedInstance * getSelection();
|
||||
@ -135,7 +132,6 @@ public:
|
||||
} spellbookSettings;
|
||||
|
||||
void update() override;
|
||||
void runLocked(std::function<void()> functor) override;
|
||||
void initializeHeroTownList();
|
||||
int getLastIndex(std::string namePrefix);
|
||||
|
||||
@ -148,11 +144,11 @@ public:
|
||||
void newStackInserted(const StackLocation &location, const CStackInstance &stack) override; //new stack inserted at given (previously empty position)
|
||||
void stacksRebalanced(const StackLocation &src, const StackLocation &dst, TQuantity count) override; //moves creatures from src stack to dst slot, may be used for merging/splittint/moving stacks
|
||||
|
||||
void artifactPut(const ArtifactLocation &al);
|
||||
void artifactRemoved(const ArtifactLocation &al);
|
||||
void artifactMoved(const ArtifactLocation &src, const ArtifactLocation &dst);
|
||||
void artifactAssembled(const ArtifactLocation &al);
|
||||
void artifactDisassembled(const ArtifactLocation &al);
|
||||
void artifactPut(const ArtifactLocation &al) override;
|
||||
void artifactRemoved(const ArtifactLocation &al) override;
|
||||
void artifactMoved(const ArtifactLocation &src, const ArtifactLocation &dst) override;
|
||||
void artifactAssembled(const ArtifactLocation &al) override;
|
||||
void artifactDisassembled(const ArtifactLocation &al) override;
|
||||
|
||||
void heroCreated(const CGHeroInstance* hero) override;
|
||||
void heroGotLevel(const CGHeroInstance *hero, PrimarySkill::PrimarySkill pskill, std::vector<SecondarySkill> &skills, QueryID queryID) override;
|
||||
@ -169,7 +165,7 @@ public:
|
||||
void showRecruitmentDialog(const CGDwelling *dwelling, const CArmedInstance *dst, int level) override;
|
||||
void showShipyardDialog(const IShipyard *obj) override; //obj may be town or shipyard;
|
||||
void showBlockingDialog(const std::string &text, const std::vector<Component> &components, QueryID askID, int soundID, bool selection, bool cancel) override; //Show a dialog, player must take decision. If selection then he has to choose between one of given components, if cancel he is allowed to not choose. After making choice, CCallback::selectionMade should be called with number of selected component (1 - n) or 0 for cancel (if allowed) and askID.
|
||||
void showTeleportDialog(TeleportChannelID channel, std::vector<ObjectInstanceID> exits, bool impassable, QueryID askID) override;
|
||||
void showTeleportDialog(TeleportChannelID channel, TTeleportExitsList exits, bool impassable, QueryID askID) override;
|
||||
void showGarrisonDialog(const CArmedInstance *up, const CGHeroInstance *down, bool removableUnits, QueryID queryID) override;
|
||||
void showPuzzleMap() override;
|
||||
void viewWorldMap() override;
|
||||
@ -196,9 +192,9 @@ public:
|
||||
void gameOver(PlayerColor player, const EVictoryLossCheckResult & victoryLossCheckResult) override;
|
||||
void playerStartsTurn(PlayerColor player) override; //called before yourTurn on active itnerface
|
||||
void showComp(const Component &comp, std::string message) override; //display component in the advmapint infobox
|
||||
void saveGame(COSer & h, const int version) override; //saving
|
||||
void loadGame(CISer & h, const int version) override; //loading
|
||||
void showWorldViewEx(const std::vector<ObjectPosInfo> & objectPositions) override;
|
||||
void saveGame(BinarySerializer & h, const int version) override; //saving
|
||||
void loadGame(BinaryDeserializer & h, const int version) override; //loading
|
||||
void showWorldViewEx(const std::vector<ObjectPosInfo> & objectPositions) override;
|
||||
|
||||
//for battles
|
||||
void actionFinished(const BattleAction& action) override;//occurs AFTER action taken by active stack or by the hero
|
||||
@ -221,6 +217,7 @@ public:
|
||||
void battleCatapultAttacked(const CatapultAttack & ca) override; //called when catapult makes an attack
|
||||
void battleStacksRemoved(const BattleStacksRemoved & bsr) override; //called when certain stack is completely removed from battlefield
|
||||
void battleObstaclePlaced(const CObstacleInstance &obstacle) override;
|
||||
void battleGateStateChanged(const EGateState state) override;
|
||||
void yourTacticPhase(int distance) override;
|
||||
|
||||
//-------------//
|
||||
@ -237,7 +234,7 @@ public:
|
||||
void openTownWindow(const CGTownInstance * town); //shows townscreen
|
||||
void openHeroWindow(const CGHeroInstance * hero); //shows hero window with given hero
|
||||
void updateInfo(const CGObjectInstance * specific);
|
||||
void init(shared_ptr<CCallback> CB);
|
||||
void init(std::shared_ptr<CCallback> CB) override;
|
||||
int3 repairScreenPos(int3 pos); //returns position closest to pos we can center screen on
|
||||
|
||||
// show dialogs
|
||||
@ -260,7 +257,6 @@ public:
|
||||
void tryDiggging(const CGHeroInstance *h);
|
||||
void showShipyardDialogOrProblemPopup(const IShipyard *obj); //obj may be town or shipyard;
|
||||
void requestReturningToMainMenu();
|
||||
void requestStoppingClient();
|
||||
void sendCustomEvent(int code);
|
||||
void proposeLoadingGame();
|
||||
|
||||
@ -270,10 +266,6 @@ public:
|
||||
CPlayerInterface(PlayerColor Player);//c-tor
|
||||
~CPlayerInterface();//d-tor
|
||||
|
||||
static CondSh<bool> terminate_cond; // confirm termination
|
||||
|
||||
|
||||
|
||||
private:
|
||||
|
||||
template <typename Handler> void serializeTempl(Handler &h, const int version);
|
||||
@ -299,9 +291,9 @@ private:
|
||||
bool duringMovement;
|
||||
bool ignoreEvents;
|
||||
|
||||
bool locked;
|
||||
|
||||
void doMoveHero(const CGHeroInstance *h, CGPath path);
|
||||
void setMovementStatus(bool value);
|
||||
void askToAssembleArtifact(const ArtifactLocation &al);
|
||||
};
|
||||
|
||||
extern CPlayerInterface * LOCPLINT;
|
||||
|
@ -2,14 +2,12 @@
|
||||
#include "CPreGame.h"
|
||||
|
||||
#include "../lib/filesystem/Filesystem.h"
|
||||
#include "../lib/filesystem/CFileInfo.h"
|
||||
#include "../lib/filesystem/CCompressedStream.h"
|
||||
|
||||
#include "../lib/CStopWatch.h"
|
||||
#include "gui/SDL_Extensions.h"
|
||||
#include "CGameInfo.h"
|
||||
#include "gui/CCursorHandler.h"
|
||||
#include "CDefHandler.h"
|
||||
#include "../lib/CGeneralTextHandler.h"
|
||||
#include "../lib/CTownHandler.h"
|
||||
#include "../lib/CHeroHandler.h"
|
||||
@ -19,7 +17,8 @@
|
||||
#include "CMusicHandler.h"
|
||||
#include "CVideoHandler.h"
|
||||
#include "Graphics.h"
|
||||
#include "../lib/Connection.h"
|
||||
#include "../lib/serializer/Connection.h"
|
||||
#include "../lib/serializer/CTypeList.h"
|
||||
#include "../lib/VCMIDirs.h"
|
||||
#include "../lib/mapping/CMap.h"
|
||||
#include "windows/GUIClasses.h"
|
||||
@ -45,8 +44,8 @@
|
||||
#include "widgets/TextControls.h"
|
||||
#include "windows/InfoWindows.h"
|
||||
#include "../lib/mapping/CMapService.h"
|
||||
#include "../lib/mapping/CMap.h"
|
||||
#include "../lib/CRandomGenerator.h"
|
||||
#include "../lib/CondSh.h"
|
||||
|
||||
/*
|
||||
* CPreGame.cpp, part of VCMI engine
|
||||
@ -206,7 +205,7 @@ public:
|
||||
template <typename T> class CApplyOnPG : public CBaseForPGApply
|
||||
{
|
||||
public:
|
||||
void applyOnPG(CSelectionScreen *selScr, void *pack) const
|
||||
void applyOnPG(CSelectionScreen *selScr, void *pack) const override
|
||||
{
|
||||
T *ptr = static_cast<T*>(pack);
|
||||
ptr->apply(selScr);
|
||||
@ -216,7 +215,7 @@ public:
|
||||
template <> class CApplyOnPG<CPack> : public CBaseForPGApply
|
||||
{
|
||||
public:
|
||||
void applyOnPG(CSelectionScreen *selScr, void *pack) const
|
||||
void applyOnPG(CSelectionScreen *selScr, void *pack) const override
|
||||
{
|
||||
logGlobal->errorStream() << "Cannot apply on PG plain CPack!";
|
||||
assert(0);
|
||||
@ -306,10 +305,10 @@ void CMenuScreen::switchToTab(size_t index)
|
||||
//funciton for std::string -> std::function conversion for main menu
|
||||
static std::function<void()> genCommand(CMenuScreen* menu, std::vector<std::string> menuType, const std::string &string)
|
||||
{
|
||||
static const std::vector<std::string> commandType =
|
||||
static const std::vector<std::string> commandType =
|
||||
{"to", "campaigns", "start", "load", "exit", "highscores"};
|
||||
|
||||
static const std::vector<std::string> gameType =
|
||||
static const std::vector<std::string> gameType =
|
||||
{"single", "multi", "campaign", "tutorial"};
|
||||
|
||||
std::list<std::string> commands;
|
||||
@ -368,7 +367,7 @@ static std::function<void()> genCommand(CMenuScreen* menu, std::vector<std::stri
|
||||
}
|
||||
}
|
||||
}
|
||||
logGlobal->errorStream()<<"Failed to parse command: "<<string;
|
||||
logGlobal->errorStream()<<"Failed to parse command: "<<string;
|
||||
return std::function<void()>();
|
||||
}
|
||||
|
||||
@ -504,19 +503,20 @@ void CGPreGame::loadGraphics()
|
||||
OBJ_CONSTRUCTION_CAPTURING_ALL;
|
||||
new CFilledTexture("DIBOXBCK", pos);
|
||||
|
||||
victory = CDefHandler::giveDef("SCNRVICT.DEF");
|
||||
loss = CDefHandler::giveDef("SCNRLOSS.DEF");
|
||||
victoryIcons = std::make_shared<CAnimation>("SCNRVICT.DEF");
|
||||
victoryIcons->load();
|
||||
lossIcons = std::make_shared<CAnimation>("SCNRLOSS.DEF");
|
||||
lossIcons->load();
|
||||
}
|
||||
|
||||
void CGPreGame::disposeGraphics()
|
||||
{
|
||||
delete victory;
|
||||
delete loss;
|
||||
victoryIcons->unload();
|
||||
lossIcons->unload();
|
||||
}
|
||||
|
||||
void CGPreGame::update()
|
||||
{
|
||||
boost::unique_lock<boost::recursive_mutex> lock(*CPlayerInterface::pim);
|
||||
if(CGP != this) //don't update if you are not a main interface
|
||||
return;
|
||||
|
||||
@ -538,15 +538,6 @@ void CGPreGame::update()
|
||||
// /FIXME: find out why GH.listInt is empty to begin with
|
||||
if (GH.topInt() != nullptr)
|
||||
GH.topInt()->show(screen);
|
||||
|
||||
if (settings["general"]["showfps"].Bool())
|
||||
GH.drawFPSCounter();
|
||||
}
|
||||
|
||||
void CGPreGame::runLocked(std::function<void()> cb)
|
||||
{
|
||||
boost::unique_lock<boost::recursive_mutex> lock(*CPlayerInterface::pim);
|
||||
cb();
|
||||
}
|
||||
|
||||
void CGPreGame::openCampaignScreen(std::string name)
|
||||
@ -563,6 +554,8 @@ CGPreGame *CGPreGame::create()
|
||||
{
|
||||
if(!CGP)
|
||||
CGP = new CGPreGame();
|
||||
|
||||
GH.terminate_cond.set(false);
|
||||
return CGP;
|
||||
}
|
||||
|
||||
@ -708,7 +701,10 @@ CSelectionScreen::CSelectionScreen(CMenuScreen::EState Type, CMenuScreen::EMulti
|
||||
if(isHost())
|
||||
{
|
||||
assert(playerNames.size() == 1 && vstd::contains(playerNames, 1)); //TODO hot-seat/network combo
|
||||
serv = sh->connectToServer();
|
||||
if(CServerHandler::DO_NOT_START_SERVER)
|
||||
serv = CServerHandler::justConnectToServer(Address, Port);
|
||||
else
|
||||
serv = sh->connectToServer();
|
||||
*serv << (ui8) 4;
|
||||
myNameID = 1;
|
||||
}
|
||||
@ -949,7 +945,7 @@ void CSelectionScreen::handleConnection()
|
||||
{
|
||||
CPackForSelectionScreen *pack = nullptr;
|
||||
*serv >> pack;
|
||||
logNetwork->traceStream() << "Received a pack of type " << typeid(*pack).name();
|
||||
logNetwork->traceStream() << "Received a pack of type " << typeid(*pack).name();
|
||||
assert(pack);
|
||||
if(QuitMenuWithoutStarting *endingPack = dynamic_cast<QuitMenuWithoutStarting *>(pack))
|
||||
{
|
||||
@ -1012,7 +1008,7 @@ void CSelectionScreen::processPacks()
|
||||
{
|
||||
CPackForSelectionScreen *pack = upcomingPacks.front();
|
||||
upcomingPacks.pop_front();
|
||||
CBaseForPGApply *apply = applier->apps[typeList.getTypeID(pack)]; //find the applier
|
||||
CBaseForPGApply *apply = applier->getApplier(typeList.getTypeID(pack)); //find the applier
|
||||
apply->applyOnPG(this, pack);
|
||||
delete pack;
|
||||
}
|
||||
@ -1105,6 +1101,10 @@ void SelectionTab::filter( int size, bool selectFirst )
|
||||
std::unordered_set<ResourceID> SelectionTab::getFiles(std::string dirURI, int resType)
|
||||
{
|
||||
boost::to_upper(dirURI);
|
||||
CResourceHandler::get()->updateFilteredFiles([&](const std::string & mount)
|
||||
{
|
||||
return boost::algorithm::starts_with(mount, dirURI);
|
||||
});
|
||||
|
||||
std::unordered_set<ResourceID> ret = CResourceHandler::get()->getFilteredFiles([&](const ResourceID & ident)
|
||||
{
|
||||
@ -1117,6 +1117,7 @@ std::unordered_set<ResourceID> SelectionTab::getFiles(std::string dirURI, int re
|
||||
|
||||
void SelectionTab::parseMaps(const std::unordered_set<ResourceID> &files)
|
||||
{
|
||||
logGlobal->debug("Parsing %d maps", files.size());
|
||||
allItems.clear();
|
||||
for(auto & file : files)
|
||||
{
|
||||
@ -1125,13 +1126,14 @@ void SelectionTab::parseMaps(const std::unordered_set<ResourceID> &files)
|
||||
CMapInfo mapInfo;
|
||||
mapInfo.mapInit(file.getName());
|
||||
|
||||
// ignore unsupported map versions (e.g. WoG maps without WoG
|
||||
if (mapInfo.mapHeader->version <= CGI->modh->settings.data["textData"]["mapVersion"].Float())
|
||||
// ignore unsupported map versions (e.g. WoG maps without WoG)
|
||||
// but accept VCMI maps
|
||||
if((mapInfo.mapHeader->version >= EMapFormat::VCMI) || (mapInfo.mapHeader->version <= CGI->modh->settings.data["textData"]["mapVersion"].Float()))
|
||||
allItems.push_back(std::move(mapInfo));
|
||||
}
|
||||
catch(std::exception & e)
|
||||
{
|
||||
logGlobal->errorStream() << "Map " << file.getName() << " is invalid. Message: " << e.what();
|
||||
logGlobal->errorStream() << "Map " << file.getName() << " is invalid. Message: " << e.what();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1142,7 +1144,7 @@ void SelectionTab::parseGames(const std::unordered_set<ResourceID> &files, bool
|
||||
{
|
||||
try
|
||||
{
|
||||
CLoadFile lf(*CResourceHandler::get()->getResourceName(file), minSupportedVersion);
|
||||
CLoadFile lf(*CResourceHandler::get()->getResourceName(file), MINIMAL_SERIALIZATION_VERSION);
|
||||
lf.checkMagicBytes(SAVEGAME_MAGIC);
|
||||
// ui8 sign[8];
|
||||
// lf >> sign;
|
||||
@ -1154,11 +1156,11 @@ void SelectionTab::parseGames(const std::unordered_set<ResourceID> &files, bool
|
||||
// Create the map info object
|
||||
CMapInfo mapInfo;
|
||||
mapInfo.mapHeader = make_unique<CMapHeader>();
|
||||
mapInfo.scenarioOpts = new StartInfo;
|
||||
mapInfo.scenarioOpts = nullptr;//to be created by serialiser
|
||||
lf >> *(mapInfo.mapHeader.get()) >> mapInfo.scenarioOpts;
|
||||
mapInfo.fileURI = file.getName();
|
||||
mapInfo.countPlayers();
|
||||
std::time_t time = CFileInfo(*CResourceHandler::get()->getResourceName(file)).getDate();
|
||||
std::time_t time = boost::filesystem::last_write_time(*CResourceHandler::get()->getResourceName(file));
|
||||
mapInfo.date = std::asctime(std::localtime(&time));
|
||||
|
||||
// If multi mode then only multi games, otherwise single
|
||||
@ -1171,7 +1173,7 @@ void SelectionTab::parseGames(const std::unordered_set<ResourceID> &files, bool
|
||||
}
|
||||
catch(const std::exception & e)
|
||||
{
|
||||
logGlobal->errorStream() << "Error: Failed to process " << file.getName() <<": " << e.what();
|
||||
logGlobal->errorStream() << "Error: Failed to process " << file.getName() <<": " << e.what();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1291,7 +1293,9 @@ SelectionTab::SelectionTab(CMenuScreen::EState Type, const std::function<void(CM
|
||||
|
||||
slider = new CSlider(Point(372, 86), tabType != CMenuScreen::saveGame ? 480 : 430, std::bind(&SelectionTab::sliderMove, this, _1), positions, curItems.size(), 0, false, CSlider::BLUE);
|
||||
slider->addUsedEvents(WHEEL);
|
||||
format = CDefHandler::giveDef("SCSELC.DEF");
|
||||
|
||||
formatIcons = std::make_shared<CAnimation>("SCSELC.DEF");
|
||||
formatIcons->load();
|
||||
|
||||
sortingBy = _format;
|
||||
ascending = true;
|
||||
@ -1320,7 +1324,7 @@ SelectionTab::SelectionTab(CMenuScreen::EState Type, const std::function<void(CM
|
||||
|
||||
SelectionTab::~SelectionTab()
|
||||
{
|
||||
delete format;
|
||||
formatIcons->unload();
|
||||
}
|
||||
|
||||
void SelectionTab::sortBy( int criteria )
|
||||
@ -1369,9 +1373,9 @@ void SelectionTab::select( int position )
|
||||
|
||||
if(txt)
|
||||
{
|
||||
std::string filename = *CResourceHandler::get("local")->getResourceName(
|
||||
auto filename = *CResourceHandler::get("local")->getResourceName(
|
||||
ResourceID(curItems[py]->fileURI, EResType::CLIENT_SAVEGAME));
|
||||
txt->setText(CFileInfo(filename).getBaseName());
|
||||
txt->setText(filename.stem().string());
|
||||
}
|
||||
|
||||
onSelect(curItems[py]);
|
||||
@ -1445,33 +1449,51 @@ void SelectionTab::printMaps(SDL_Surface *to)
|
||||
}
|
||||
printAtMiddleLoc(temp2, 70, 128 + line * 25, FONT_SMALL, itemColor, to);
|
||||
|
||||
int temp=-1;
|
||||
int frame = -1, group = 0;
|
||||
switch (currentItem->mapHeader->version)
|
||||
{
|
||||
case EMapFormat::ROE:
|
||||
temp=0;
|
||||
frame = 0;
|
||||
break;
|
||||
case EMapFormat::AB:
|
||||
temp=1;
|
||||
frame = 1;
|
||||
break;
|
||||
case EMapFormat::SOD:
|
||||
temp=2;
|
||||
frame = 2;
|
||||
break;
|
||||
case EMapFormat::WOG:
|
||||
temp=3;
|
||||
frame = 3;
|
||||
break;
|
||||
case EMapFormat::VCMI:
|
||||
frame = 0;
|
||||
group = 1;
|
||||
break;
|
||||
default:
|
||||
// Unknown version. Be safe and ignore that map
|
||||
logGlobal->warnStream() << "Warning: " << currentItem->fileURI << " has wrong version!";
|
||||
logGlobal->warnStream() << "Warning: " << currentItem->fileURI << " has wrong version!";
|
||||
continue;
|
||||
}
|
||||
blitAtLoc(format->ourImages[temp].bitmap, 88, 117 + line * 25, to);
|
||||
IImage * icon = formatIcons->getImage(frame,group);
|
||||
if(icon)
|
||||
{
|
||||
icon->draw(to, pos.x + 88, pos.y + 117 + line * 25);
|
||||
icon->decreaseRef();
|
||||
}
|
||||
|
||||
//victory conditions
|
||||
blitAtLoc(CGP->victory->ourImages[currentItem->mapHeader->victoryIconIndex].bitmap, 306, 117 + line * 25, to);
|
||||
|
||||
icon = CGP->victoryIcons->getImage(currentItem->mapHeader->victoryIconIndex,0);
|
||||
if(icon)
|
||||
{
|
||||
icon->draw(to, pos.x + 306, pos.y + 117 + line * 25);
|
||||
icon->decreaseRef();
|
||||
}
|
||||
//loss conditions
|
||||
blitAtLoc(CGP->loss->ourImages[currentItem->mapHeader->defeatIconIndex].bitmap, 339, 117 + line * 25, to);
|
||||
icon = CGP->lossIcons->getImage(currentItem->mapHeader->defeatIconIndex,0);
|
||||
if(icon)
|
||||
{
|
||||
icon->draw(to, pos.x + 339, pos.y + 117 + line * 25);
|
||||
icon->decreaseRef();
|
||||
}
|
||||
}
|
||||
else //if campaign
|
||||
{
|
||||
@ -1494,8 +1516,8 @@ void SelectionTab::printMaps(SDL_Surface *to)
|
||||
}
|
||||
else
|
||||
{
|
||||
name = CFileInfo(*CResourceHandler::get("local")->getResourceName(
|
||||
ResourceID(currentItem->fileURI, EResType::CLIENT_SAVEGAME))).getBaseName();
|
||||
name = CResourceHandler::get("local")->getResourceName(
|
||||
ResourceID(currentItem->fileURI, EResType::CLIENT_SAVEGAME))->stem().string();
|
||||
}
|
||||
|
||||
//print name
|
||||
@ -1671,7 +1693,7 @@ CRandomMapTab::CRandomMapTab()
|
||||
{
|
||||
mapGenOptions.setPlayerCount(btnId);
|
||||
deactivateButtonsFrom(teamsCntGroup, btnId);
|
||||
deactivateButtonsFrom(compOnlyPlayersCntGroup, 8 - btnId + 1);
|
||||
deactivateButtonsFrom(compOnlyPlayersCntGroup, btnId);
|
||||
validatePlayersCnt(btnId);
|
||||
if(!SEL->isGuest())
|
||||
updateMapInfo();
|
||||
@ -1694,7 +1716,6 @@ CRandomMapTab::CRandomMapTab()
|
||||
compOnlyPlayersCntGroup->pos.y += 285;
|
||||
compOnlyPlayersCntGroup->pos.x += BTNS_GROUP_LEFT_MARGIN;
|
||||
addButtonsWithRandToGroup(compOnlyPlayersCntGroup, numberDefs, 0, 7, NUMBERS_WIDTH, 224, 232);
|
||||
compOnlyPlayersCntGroup->setSelected(0);
|
||||
compOnlyPlayersCntGroup->addCallback([&](int btnId)
|
||||
{
|
||||
mapGenOptions.setCompOnlyPlayerCount(btnId);
|
||||
@ -1808,9 +1829,9 @@ void CRandomMapTab::validatePlayersCnt(int playersCnt)
|
||||
mapGenOptions.setTeamCount(playersCnt - 1);
|
||||
teamsCntGroup->setSelected(mapGenOptions.getTeamCount());
|
||||
}
|
||||
if(mapGenOptions.getCompOnlyPlayerCount() > 8 - playersCnt)
|
||||
if(mapGenOptions.getCompOnlyPlayerCount() >= playersCnt)
|
||||
{
|
||||
mapGenOptions.setCompOnlyPlayerCount(8 - playersCnt);
|
||||
mapGenOptions.setCompOnlyPlayerCount(playersCnt - 1);
|
||||
compOnlyPlayersCntGroup->setSelected(mapGenOptions.getCompOnlyPlayerCount());
|
||||
}
|
||||
|
||||
@ -1883,9 +1904,9 @@ void CRandomMapTab::updateMapInfo()
|
||||
|
||||
// Generate player information
|
||||
mapInfo->mapHeader->players.clear();
|
||||
int playersToGen = (mapGenOptions.getPlayerCount() == CMapGenOptions::RANDOM_SIZE
|
||||
|| mapGenOptions.getCompOnlyPlayerCount() == CMapGenOptions::RANDOM_SIZE)
|
||||
? 8 : mapGenOptions.getPlayerCount() + mapGenOptions.getCompOnlyPlayerCount();
|
||||
int playersToGen = PlayerColor::PLAYER_LIMIT_I;
|
||||
if(mapGenOptions.getPlayerCount() != CMapGenOptions::RANDOM_SIZE)
|
||||
playersToGen = mapGenOptions.getPlayerCount();
|
||||
mapInfo->mapHeader->howManyTeams = playersToGen;
|
||||
|
||||
for(int i = 0; i < playersToGen; ++i)
|
||||
@ -1893,7 +1914,8 @@ void CRandomMapTab::updateMapInfo()
|
||||
PlayerInfo player;
|
||||
player.isFactionRandom = true;
|
||||
player.canComputerPlay = true;
|
||||
if(i >= mapGenOptions.getPlayerCount() && mapGenOptions.getPlayerCount() != CMapGenOptions::RANDOM_SIZE)
|
||||
if(mapGenOptions.getCompOnlyPlayerCount() != CMapGenOptions::RANDOM_SIZE &&
|
||||
i >= mapGenOptions.getHumanOnlyPlayerCount())
|
||||
{
|
||||
player.canHumanPlay = false;
|
||||
}
|
||||
@ -1925,7 +1947,7 @@ const CMapGenOptions & CRandomMapTab::getMapGenOptions() const
|
||||
return mapGenOptions;
|
||||
}
|
||||
|
||||
void CRandomMapTab::setMapGenOptions(shared_ptr<CMapGenOptions> opts)
|
||||
void CRandomMapTab::setMapGenOptions(std::shared_ptr<CMapGenOptions> opts)
|
||||
{
|
||||
mapSizeBtnGroup->setSelected(vstd::find_pos(getPossibleMapSizes(), opts->getWidth()));
|
||||
twoLevelsBtn->setSelected(opts->getHasTwoLevels());
|
||||
@ -1973,8 +1995,8 @@ void CChatBox::addNewMessage(const std::string &text)
|
||||
}
|
||||
|
||||
InfoCard::InfoCard( bool Network )
|
||||
: bg(nullptr), network(Network), chatOn(false), chat(nullptr), playerListBg(nullptr),
|
||||
difficulty(nullptr), sizes(nullptr), sFlags(nullptr)
|
||||
: sizes(nullptr), bg(nullptr), network(Network), chatOn(false), chat(nullptr), playerListBg(nullptr),
|
||||
difficulty(nullptr)
|
||||
{
|
||||
OBJ_CONSTRUCTION_CAPTURING_ALL;
|
||||
CIntObject::type |= REDRAW_PARENT;
|
||||
@ -2000,8 +2022,11 @@ InfoCard::InfoCard( bool Network )
|
||||
parent->children.pop_back();
|
||||
pos.w = bg->pos.w;
|
||||
pos.h = bg->pos.h;
|
||||
sizes = CDefHandler::giveDef("SCNRMPSZ.DEF");
|
||||
sFlags = CDefHandler::giveDef("ITGFLAGS.DEF");
|
||||
sizes = new CAnimImage("SCNRMPSZ", 4, 0, 318, 22);//let it be custom size (frame 4) by default
|
||||
sizes->recActions &= ~(SHOWALL | UPDATE);//explicit draw
|
||||
|
||||
sFlags = std::make_shared<CAnimation>("ITGFLAGS.DEF");
|
||||
sFlags->load();
|
||||
difficulty = new CToggleGroup(0);
|
||||
{
|
||||
static const char *difButns[] = {"GSPBUT3.DEF", "GSPBUT4.DEF", "GSPBUT5.DEF", "GSPBUT6.DEF", "GSPBUT7.DEF"};
|
||||
@ -2026,12 +2051,16 @@ InfoCard::InfoCard( bool Network )
|
||||
}
|
||||
}
|
||||
|
||||
victory = new CAnimImage("SCNRVICT",0, 0, 24, 302);
|
||||
victory->recActions &= ~(SHOWALL | UPDATE);//explicit draw
|
||||
loss = new CAnimImage("SCNRLOSS", 0, 0, 24, 359);
|
||||
loss->recActions &= ~(SHOWALL | UPDATE);//explicit draw
|
||||
}
|
||||
|
||||
InfoCard::~InfoCard()
|
||||
{
|
||||
delete sizes;
|
||||
delete sFlags;
|
||||
if(sFlags)
|
||||
sFlags->unload();
|
||||
}
|
||||
|
||||
void InfoCard::showAll(SDL_Surface * to)
|
||||
@ -2079,27 +2108,17 @@ void InfoCard::showAll(SDL_Surface * to)
|
||||
{
|
||||
if(SEL->screenType != CMenuScreen::campaignList)
|
||||
{
|
||||
int temp = -1;
|
||||
|
||||
if(!chatOn)
|
||||
{
|
||||
CDefHandler * loss = CGP ? CGP->loss : CDefHandler::giveDef("SCNRLOSS.DEF");
|
||||
CDefHandler * victory = CGP ? CGP->victory : CDefHandler::giveDef("SCNRVICT.DEF");
|
||||
|
||||
CMapHeader * header = SEL->current->mapHeader.get();
|
||||
//victory conditions
|
||||
printAtLoc(header->victoryMessage, 60, 307, FONT_SMALL, Colors::WHITE, to);
|
||||
blitAtLoc(victory->ourImages[header->victoryIconIndex].bitmap, 24, 302, to); //victory cond descr
|
||||
|
||||
victory->setFrame(header->victoryIconIndex);
|
||||
victory->showAll(to);
|
||||
//loss conditoins
|
||||
printAtLoc(header->defeatMessage, 60, 366, FONT_SMALL, Colors::WHITE, to);
|
||||
blitAtLoc(loss->ourImages[header->defeatIconIndex].bitmap, 24, 359, to); //loss cond
|
||||
|
||||
if (!CGP)
|
||||
{
|
||||
delete loss;
|
||||
delete victory;
|
||||
}
|
||||
loss->setFrame(header->defeatIconIndex);
|
||||
loss->showAll(to);
|
||||
}
|
||||
|
||||
//difficulty
|
||||
@ -2111,23 +2130,22 @@ void InfoCard::showAll(SDL_Surface * to)
|
||||
switch (SEL->current->mapHeader->width)
|
||||
{
|
||||
case 36:
|
||||
temp=0;
|
||||
sizes->setFrame(0);
|
||||
break;
|
||||
case 72:
|
||||
temp=1;
|
||||
sizes->setFrame(1);
|
||||
break;
|
||||
case 108:
|
||||
temp=2;
|
||||
sizes->setFrame(2);
|
||||
break;
|
||||
case 144:
|
||||
temp=3;
|
||||
sizes->setFrame(3);
|
||||
break;
|
||||
default:
|
||||
temp=4;
|
||||
sizes->setFrame(4);
|
||||
break;
|
||||
}
|
||||
blitAtLoc(sizes->ourImages[temp].bitmap, 318, 22, to);
|
||||
|
||||
sizes->showAll(to);
|
||||
|
||||
if(SEL->screenType == CMenuScreen::loadGame)
|
||||
printToLoc((static_cast<const CMapInfo*>(SEL->current))->date,308,34, FONT_SMALL, Colors::WHITE, to);
|
||||
@ -2146,8 +2164,10 @@ void InfoCard::showAll(SDL_Surface * to)
|
||||
for (auto i = SEL->sInfo.playerInfos.cbegin(); i != SEL->sInfo.playerInfos.cend(); i++)
|
||||
{
|
||||
int *myx = ((i->first == playerColor || SEL->current->mapHeader->players[i->first.getNum()].team == myT) ? &fx : &ex);
|
||||
blitAtLoc(sFlags->ourImages[i->first.getNum()].bitmap, *myx, 399, to);
|
||||
*myx += sFlags->ourImages[i->first.getNum()].bitmap->w;
|
||||
IImage * flag = sFlags->getImage(i->first.getNum(),0);
|
||||
flag->draw(to, pos.x + *myx, pos.y + 399);
|
||||
*myx += flag->width();
|
||||
flag->decreaseRef();
|
||||
}
|
||||
|
||||
std::string tob;
|
||||
@ -2242,7 +2262,9 @@ void InfoCard::showTeamsPopup()
|
||||
int curx = 128 - 9*flags.size();
|
||||
for(auto & flag : flags)
|
||||
{
|
||||
blitAt(sFlags->ourImages[flag].bitmap, curx, 75 + 50*i, bmp);
|
||||
IImage * icon = sFlags->getImage(flag,0);
|
||||
icon->draw(bmp, curx, 75 + 50*i);
|
||||
icon->decreaseRef();
|
||||
curx += 18;
|
||||
}
|
||||
}
|
||||
@ -3124,14 +3146,17 @@ void CMultiMode::hostTCP()
|
||||
Settings name = settings.write["general"]["playerName"];
|
||||
name->String() = txt->text;
|
||||
GH.popIntTotally(this);
|
||||
GH.pushInt(new CSelectionScreen(CMenuScreen::newGame, CMenuScreen::MULTI_NETWORK_HOST));
|
||||
if(CServerHandler::DO_NOT_START_SERVER)
|
||||
GH.pushInt(new CSimpleJoinScreen(CMenuScreen::MULTI_NETWORK_HOST));
|
||||
else
|
||||
GH.pushInt(new CSelectionScreen(CMenuScreen::newGame, CMenuScreen::MULTI_NETWORK_HOST));
|
||||
}
|
||||
|
||||
void CMultiMode::joinTCP()
|
||||
{
|
||||
Settings name = settings.write["general"]["playerName"];
|
||||
name->String() = txt->text;
|
||||
GH.pushInt(new CSimpleJoinScreen);
|
||||
GH.pushInt(new CSimpleJoinScreen(CMenuScreen::MULTI_NETWORK_GUEST));
|
||||
}
|
||||
|
||||
CHotSeatPlayers::CHotSeatPlayers(const std::string &firstPlayer)
|
||||
@ -3226,7 +3251,8 @@ void CBonusSelection::init()
|
||||
graphics->fonts[FONT_BIG]->renderTextLeft(background, CGI->generaltexth->allTexts[508], Colors::YELLOW, Point(481, 28));
|
||||
|
||||
//map size icon
|
||||
sizes = CDefHandler::giveDef("SCNRMPSZ.DEF");
|
||||
sizes = new CAnimImage("SCNRMPSZ",4,0,735, 26);
|
||||
sizes->recActions &= ~(SHOWALL | UPDATE);//explicit draw
|
||||
|
||||
//campaign description
|
||||
graphics->fonts[FONT_SMALL]->renderTextLeft(background, CGI->generaltexth->allTexts[38], Colors::YELLOW, Point(481, 63));
|
||||
@ -3277,14 +3303,10 @@ void CBonusSelection::init()
|
||||
graphics->fonts[FONT_MEDIUM]->renderTextLeft(background, difficulty.back(), Colors::WHITE, Point(689, 432));
|
||||
|
||||
//difficulty pics
|
||||
for (int b=0; b<ARRAY_COUNT(diffPics); ++b)
|
||||
for (size_t b=0; b < diffPics.size(); ++b)
|
||||
{
|
||||
CDefEssential * cde = CDefHandler::giveDefEss("GSPBUT" + boost::lexical_cast<std::string>(b+3) + ".DEF");
|
||||
SDL_Surface * surfToDuplicate = cde->ourImages[0].bitmap;
|
||||
diffPics[b] = SDL_ConvertSurface(surfToDuplicate, surfToDuplicate->format,
|
||||
surfToDuplicate->flags);
|
||||
|
||||
delete cde;
|
||||
diffPics[b] = new CAnimImage("GSPBUT" + boost::lexical_cast<std::string>(b+3) + ".DEF", 0, 0, 709, 455);
|
||||
diffPics[b]->recActions &= ~(SHOWALL | UPDATE);//explicit draw
|
||||
}
|
||||
|
||||
//difficulty selection buttons
|
||||
@ -3295,30 +3317,26 @@ void CBonusSelection::init()
|
||||
}
|
||||
|
||||
//load miniflags
|
||||
sFlags = CDefHandler::giveDef("ITGFLAGS.DEF");
|
||||
sFlags = std::make_shared<CAnimation>("ITGFLAGS.DEF");
|
||||
sFlags->load();
|
||||
}
|
||||
|
||||
CBonusSelection::CBonusSelection(shared_ptr<CCampaignState> _ourCampaign) : ourCampaign(_ourCampaign)
|
||||
CBonusSelection::CBonusSelection(std::shared_ptr<CCampaignState> _ourCampaign) : ourCampaign(_ourCampaign)
|
||||
{
|
||||
init();
|
||||
}
|
||||
|
||||
CBonusSelection::CBonusSelection(const std::string & campaignFName)
|
||||
{
|
||||
ourCampaign = make_shared<CCampaignState>(CCampaignHandler::getCampaign(campaignFName));
|
||||
ourCampaign = std::make_shared<CCampaignState>(CCampaignHandler::getCampaign(campaignFName));
|
||||
init();
|
||||
}
|
||||
|
||||
CBonusSelection::~CBonusSelection()
|
||||
{
|
||||
SDL_FreeSurface(background);
|
||||
delete sizes;
|
||||
delete ourHeader;
|
||||
delete sFlags;
|
||||
for (auto & elem : diffPics)
|
||||
{
|
||||
SDL_FreeSurface(elem);
|
||||
}
|
||||
sFlags->unload();
|
||||
}
|
||||
|
||||
void CBonusSelection::goBack()
|
||||
@ -3417,8 +3435,6 @@ void CBonusSelection::selectMap(int mapNr, bool initialSelect)
|
||||
|
||||
void CBonusSelection::show(SDL_Surface * to)
|
||||
{
|
||||
//blitAt(background, pos.x, pos.y, to);
|
||||
|
||||
//map name
|
||||
std::string mapName = ourHeader->name;
|
||||
|
||||
@ -3452,7 +3468,8 @@ void CBonusSelection::show(SDL_Surface * to)
|
||||
temp=4;
|
||||
break;
|
||||
}
|
||||
blitAtLoc(sizes->ourImages[temp].bitmap, 735, 26, to);
|
||||
sizes->setFrame(temp);
|
||||
sizes->showAll(to);
|
||||
|
||||
//flags
|
||||
int fx = 496 + graphics->fonts[FONT_SMALL]->getStringWidth(CGI->generaltexth->allTexts[390]);
|
||||
@ -3462,12 +3479,15 @@ void CBonusSelection::show(SDL_Surface * to)
|
||||
for (auto i = startInfo.playerInfos.cbegin(); i != startInfo.playerInfos.cend(); i++)
|
||||
{
|
||||
int *myx = ((i->first == playerColor || ourHeader->players[i->first.getNum()].team == myT) ? &fx : &ex);
|
||||
blitAtLoc(sFlags->ourImages[i->first.getNum()].bitmap, *myx, 405, to);
|
||||
*myx += sFlags->ourImages[i->first.getNum()].bitmap->w;
|
||||
|
||||
IImage * flag = sFlags->getImage(i->first.getNum(),0);
|
||||
flag->draw(to, pos.x + *myx, pos.y + 405);
|
||||
*myx += flag->width();
|
||||
flag->decreaseRef();
|
||||
}
|
||||
|
||||
//difficulty
|
||||
blitAtLoc(diffPics[startInfo.difficulty], 709, 455, to);
|
||||
diffPics[startInfo.difficulty]->showAll(to);
|
||||
|
||||
CIntObject::show(to);
|
||||
}
|
||||
@ -3651,7 +3671,7 @@ void CBonusSelection::updateBonusSelection()
|
||||
if (picNumber != -1)
|
||||
picName += ":" + boost::lexical_cast<std::string>(picNumber);
|
||||
|
||||
auto anim = new CAnimation();
|
||||
auto anim = std::make_shared<CAnimation>();
|
||||
anim->setCustom(picName, 0);
|
||||
bonusButton->setImage(anim);
|
||||
const SDL_Color brightYellow = { 242, 226, 110, 0 };
|
||||
@ -4268,7 +4288,7 @@ void CPrologEpilogVideo::clickLeft( tribool down, bool previousState )
|
||||
exitCb();
|
||||
}
|
||||
|
||||
CSimpleJoinScreen::CSimpleJoinScreen()
|
||||
CSimpleJoinScreen::CSimpleJoinScreen(CMenuScreen::EMultiMode mode)
|
||||
{
|
||||
OBJ_CONSTRUCTION_CAPTURING_ALL;
|
||||
bg = new CPicture("MUDIALOG.bmp"); // address background
|
||||
@ -4284,7 +4304,7 @@ CSimpleJoinScreen::CSimpleJoinScreen()
|
||||
port->cb += std::bind(&CSimpleJoinScreen::onChange, this, _1);
|
||||
port->filters += std::bind(&CTextInput::numberFilter, _1, _2, 0, 65535);
|
||||
|
||||
ok = new CButton(Point( 26, 142), "MUBCHCK.DEF", CGI->generaltexth->zelp[560], std::bind(&CSimpleJoinScreen::enterSelectionScreen, this), SDLK_RETURN);
|
||||
ok = new CButton(Point( 26, 142), "MUBCHCK.DEF", CGI->generaltexth->zelp[560], std::bind(&CSimpleJoinScreen::enterSelectionScreen, this, mode), SDLK_RETURN);
|
||||
cancel = new CButton(Point(142, 142), "MUBCANC.DEF", CGI->generaltexth->zelp[561], std::bind(&CGuiHandler::popIntTotally, std::ref(GH), this), SDLK_ESCAPE);
|
||||
bar = new CGStatusBar(new CPicture(Rect(7, 186, 218, 18), 0));
|
||||
|
||||
@ -4293,15 +4313,15 @@ CSimpleJoinScreen::CSimpleJoinScreen()
|
||||
address->giveFocus();
|
||||
}
|
||||
|
||||
void CSimpleJoinScreen::enterSelectionScreen()
|
||||
void CSimpleJoinScreen::enterSelectionScreen(CMenuScreen::EMultiMode mode)
|
||||
{
|
||||
std::string textAddress = address->text;
|
||||
std::string textPort = port->text;
|
||||
|
||||
GH.popIntTotally(this);
|
||||
GH.pushInt(new CSelectionScreen(CMenuScreen::newGame, CMenuScreen::MULTI_NETWORK_GUEST, nullptr, textAddress, textPort));
|
||||
}
|
||||
|
||||
GH.pushInt(new CSelectionScreen(CMenuScreen::newGame, mode, nullptr, textAddress, textPort));
|
||||
}
|
||||
void CSimpleJoinScreen::onChange(const std::string & newText)
|
||||
{
|
||||
ok->block(address->text.empty() || port->text.empty());
|
||||
|
@ -1,6 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
//#include "../lib/filesystem/Filesystem.h"
|
||||
#include "../lib/StartInfo.h"
|
||||
#include "../lib/FunctionList.h"
|
||||
#include "../lib/mapping/CMapInfo.h"
|
||||
@ -36,7 +35,11 @@ class CMultiLineLabel;
|
||||
class CToggleButton;
|
||||
class CToggleGroup;
|
||||
class CTabbedInt;
|
||||
class IImage;
|
||||
class CAnimation;
|
||||
class CAnimImage;
|
||||
class CButton;
|
||||
class CLabel;
|
||||
class CSlider;
|
||||
|
||||
namespace boost{ class thread; class recursive_mutex;}
|
||||
@ -75,10 +78,10 @@ public:
|
||||
};
|
||||
CMenuScreen(const JsonNode& configNode);
|
||||
|
||||
void showAll(SDL_Surface * to);
|
||||
void show(SDL_Surface * to);
|
||||
void activate();
|
||||
void deactivate();
|
||||
void showAll(SDL_Surface * to) override;
|
||||
void show(SDL_Surface * to) override;
|
||||
void activate() override;
|
||||
void deactivate() override;
|
||||
|
||||
void switchToTab(size_t index);
|
||||
};
|
||||
@ -100,10 +103,10 @@ class CreditsScreen : public CIntObject
|
||||
public:
|
||||
CreditsScreen();
|
||||
|
||||
void show(SDL_Surface * to);
|
||||
void show(SDL_Surface * to) override;
|
||||
|
||||
void clickLeft(tribool down, bool previousState);
|
||||
void clickRight(tribool down, bool previousState);
|
||||
void clickLeft(tribool down, bool previousState) override;
|
||||
void clickRight(tribool down, bool previousState) override;
|
||||
};
|
||||
|
||||
/// Implementation of the chat box
|
||||
@ -115,13 +118,15 @@ public:
|
||||
|
||||
CChatBox(const Rect &rect);
|
||||
|
||||
void keyPressed(const SDL_KeyboardEvent & key);
|
||||
void keyPressed(const SDL_KeyboardEvent & key) override;
|
||||
|
||||
void addNewMessage(const std::string &text);
|
||||
};
|
||||
|
||||
class InfoCard : public CIntObject
|
||||
{
|
||||
CAnimImage * victory, * loss, *sizes;
|
||||
std::shared_ptr<CAnimation> sFlags;
|
||||
public:
|
||||
CPicture *bg;
|
||||
CMenuScreen::EState type;
|
||||
@ -133,11 +138,10 @@ public:
|
||||
CPicture *playerListBg;
|
||||
|
||||
CToggleGroup *difficulty;
|
||||
CDefHandler *sizes, *sFlags;
|
||||
|
||||
void changeSelection(const CMapInfo *to);
|
||||
void showAll(SDL_Surface * to);
|
||||
void clickRight(tribool down, bool previousState);
|
||||
void showAll(SDL_Surface * to) override;
|
||||
void clickRight(tribool down, bool previousState) override;
|
||||
void showTeamsPopup();
|
||||
void toggleChat();
|
||||
void setChat(bool activateChat);
|
||||
@ -149,9 +153,9 @@ public:
|
||||
class SelectionTab : public CIntObject
|
||||
{
|
||||
private:
|
||||
CDefHandler *format; //map size
|
||||
std::shared_ptr<CAnimation> formatIcons;
|
||||
|
||||
void parseMaps(const std::unordered_set<ResourceID> &files);
|
||||
void parseMaps(const std::unordered_set<ResourceID> &files);
|
||||
void parseGames(const std::unordered_set<ResourceID> &files, bool multi);
|
||||
void parseCampaigns(const std::unordered_set<ResourceID> & files );
|
||||
std::unordered_set<ResourceID> getFiles(std::string dirURI, int resType);
|
||||
@ -184,10 +188,10 @@ public:
|
||||
void selectFName(std::string fname);
|
||||
const CMapInfo * getSelectedMapInfo() const;
|
||||
|
||||
void showAll(SDL_Surface * to);
|
||||
void clickLeft(tribool down, bool previousState);
|
||||
void keyPressed(const SDL_KeyboardEvent & key);
|
||||
void onDoubleClick();
|
||||
void showAll(SDL_Surface * to) override;
|
||||
void clickLeft(tribool down, bool previousState) override;
|
||||
void keyPressed(const SDL_KeyboardEvent & key) override;
|
||||
void onDoubleClick() override;
|
||||
SelectionTab(CMenuScreen::EState Type, const std::function<void(CMapInfo *)> &OnSelect, CMenuScreen::EMultiMode MultiPlayer = CMenuScreen::SINGLE_PLAYER);
|
||||
~SelectionTab();
|
||||
};
|
||||
@ -235,7 +239,7 @@ public:
|
||||
CLabel *subtitle;
|
||||
|
||||
SelectedBox(Point position, PlayerSettings & settings, SelType type);
|
||||
void clickRight(tribool down, bool previousState);
|
||||
void clickRight(tribool down, bool previousState) override;
|
||||
|
||||
void update();
|
||||
};
|
||||
@ -254,7 +258,7 @@ public:
|
||||
|
||||
PlayerOptionsEntry(OptionsTab *owner, PlayerSettings &S);
|
||||
void selectButtons(); //hides unavailable buttons
|
||||
void showAll(SDL_Surface * to);
|
||||
void showAll(SDL_Surface * to) override;
|
||||
void update();
|
||||
};
|
||||
|
||||
@ -282,7 +286,7 @@ public:
|
||||
void recreate();
|
||||
OptionsTab();
|
||||
~OptionsTab();
|
||||
void showAll(SDL_Surface * to);
|
||||
void showAll(SDL_Surface * to) override;
|
||||
|
||||
int nextAllowedHero(PlayerColor player, int min, int max, int incl, int dir );
|
||||
|
||||
@ -295,12 +299,12 @@ class CRandomMapTab : public CIntObject
|
||||
public:
|
||||
CRandomMapTab();
|
||||
|
||||
void showAll(SDL_Surface * to);
|
||||
void showAll(SDL_Surface * to) override;
|
||||
void updateMapInfo();
|
||||
CFunctionList<void (const CMapInfo *)> & getMapInfoChanged();
|
||||
const CMapInfo * getMapInfo() const;
|
||||
const CMapGenOptions & getMapGenOptions() const;
|
||||
void setMapGenOptions(shared_ptr<CMapGenOptions> opts);
|
||||
void setMapGenOptions(std::shared_ptr<CMapGenOptions> opts);
|
||||
|
||||
private:
|
||||
void addButtonsToGroup(CToggleGroup * group, const std::vector<std::string> & defs, int startIndex, int endIndex, int btnWidth, int helpStartIndex) const;
|
||||
@ -316,7 +320,7 @@ private:
|
||||
* compOnlyTeamsCntGroup, * waterContentGroup, * monsterStrengthGroup;
|
||||
CButton * showRandMaps;
|
||||
CMapGenOptions mapGenOptions;
|
||||
unique_ptr<CMapInfo> mapInfo;
|
||||
std::unique_ptr<CMapInfo> mapInfo;
|
||||
CFunctionList<void(const CMapInfo *)> mapInfoChanged;
|
||||
};
|
||||
|
||||
@ -385,7 +389,7 @@ public:
|
||||
void postRequest(ui8 what, ui8 dir) override;
|
||||
void postChatMessage(const std::string &txt) override;
|
||||
void propagateNames();
|
||||
void showAll(SDL_Surface *to);
|
||||
void showAll(SDL_Surface *to) override;
|
||||
};
|
||||
|
||||
/// Save game screen
|
||||
@ -454,8 +458,8 @@ class CPrologEpilogVideo : public CWindowObject
|
||||
public:
|
||||
CPrologEpilogVideo(CCampaignScenario::SScenarioPrologEpilog _spe, std::function<void()> callback);
|
||||
|
||||
void clickLeft(tribool down, bool previousState);
|
||||
void show(SDL_Surface * to);
|
||||
void clickLeft(tribool down, bool previousState) override;
|
||||
void show(SDL_Surface * to) override;
|
||||
};
|
||||
|
||||
/// Campaign screen where you can choose one out of three starting bonuses
|
||||
@ -463,7 +467,7 @@ class CBonusSelection : public CIntObject
|
||||
{
|
||||
public:
|
||||
CBonusSelection(const std::string & campaignFName);
|
||||
CBonusSelection(shared_ptr<CCampaignState> _ourCampaign);
|
||||
CBonusSelection(std::shared_ptr<CCampaignState> _ourCampaign);
|
||||
~CBonusSelection();
|
||||
|
||||
void showAll(SDL_Surface * to) override;
|
||||
@ -498,9 +502,9 @@ private:
|
||||
CRegion(CBonusSelection * _owner, bool _accessible, bool _selectable, int _myNumber);
|
||||
~CRegion();
|
||||
|
||||
void clickLeft(tribool down, bool previousState);
|
||||
void clickRight(tribool down, bool previousState);
|
||||
void show(SDL_Surface * to);
|
||||
void clickLeft(tribool down, bool previousState) override;
|
||||
void clickRight(tribool down, bool previousState) override;
|
||||
void show(SDL_Surface * to) override;
|
||||
};
|
||||
|
||||
void init();
|
||||
@ -526,13 +530,13 @@ private:
|
||||
std::vector<CRegion *> regions;
|
||||
CRegion * highlightedRegion;
|
||||
CToggleGroup * bonuses;
|
||||
SDL_Surface * diffPics[5]; //pictures of difficulties, user-selectable (or not if campaign locks this)
|
||||
std::array<CAnimImage *, 5> diffPics; //pictures of difficulties, user-selectable (or not if campaign locks this)
|
||||
CButton * diffLb, * diffRb; //buttons for changing difficulty
|
||||
CDefHandler * sizes; //icons of map sizes
|
||||
CDefHandler * sFlags;
|
||||
CAnimImage * sizes;//icons of map sizes
|
||||
std::shared_ptr<CAnimation> sFlags;
|
||||
|
||||
// Data
|
||||
shared_ptr<CCampaignState> ourCampaign;
|
||||
std::shared_ptr<CCampaignState> ourCampaign;
|
||||
int selectedMap;
|
||||
boost::optional<int> selectedBonus;
|
||||
StartInfo startInfo;
|
||||
@ -560,12 +564,12 @@ private:
|
||||
std::string video; // the resource name of the video
|
||||
std::string hoverText;
|
||||
|
||||
void clickLeft(tribool down, bool previousState);
|
||||
void hover(bool on);
|
||||
void clickLeft(tribool down, bool previousState) override;
|
||||
void hover(bool on) override;
|
||||
|
||||
public:
|
||||
CCampaignButton(const JsonNode &config );
|
||||
void show(SDL_Surface * to);
|
||||
void show(SDL_Surface * to) override;
|
||||
};
|
||||
|
||||
CButton *back;
|
||||
@ -578,7 +582,7 @@ public:
|
||||
enum CampaignSet {ROE, AB, SOD, WOG};
|
||||
|
||||
CCampaignScreen(const JsonNode &config);
|
||||
void showAll(SDL_Surface *to);
|
||||
void showAll(SDL_Surface *to) override;
|
||||
};
|
||||
|
||||
/// Manages the configuration of pregame GUI elements like campaign screen, main menu, loading screen,...
|
||||
@ -597,7 +601,7 @@ private:
|
||||
};
|
||||
|
||||
/// Handles background screen, loads graphics for victory/loss condition and random town or hero selection
|
||||
class CGPreGame : public CIntObject, public ILockedUpdatable
|
||||
class CGPreGame : public CIntObject, public IUpdateable
|
||||
{
|
||||
void loadGraphics();
|
||||
void disposeGraphics();
|
||||
@ -607,11 +611,10 @@ class CGPreGame : public CIntObject, public ILockedUpdatable
|
||||
public:
|
||||
CMenuScreen * menu;
|
||||
|
||||
CDefHandler *victory, *loss;
|
||||
std::shared_ptr<CAnimation> victoryIcons, lossIcons;
|
||||
|
||||
~CGPreGame();
|
||||
void update() override;
|
||||
void runLocked(std::function<void()> cb) override;
|
||||
void openSel(CMenuScreen::EState type, CMenuScreen::EMultiMode multi = CMenuScreen::SINGLE_PLAYER);
|
||||
|
||||
void openCampaignScreen(std::string name);
|
||||
@ -630,7 +633,7 @@ public:
|
||||
CLoadingScreen(std::function<void()> loader);
|
||||
~CLoadingScreen();
|
||||
|
||||
void showAll(SDL_Surface *to);
|
||||
void showAll(SDL_Surface *to) override;
|
||||
};
|
||||
|
||||
/// Simple window to enter the server's address.
|
||||
@ -643,10 +646,10 @@ class CSimpleJoinScreen : public CIntObject
|
||||
CTextInput * address;
|
||||
CTextInput * port;
|
||||
|
||||
void enterSelectionScreen();
|
||||
void enterSelectionScreen(CMenuScreen::EMultiMode mode);
|
||||
void onChange(const std::string & newText);
|
||||
public:
|
||||
CSimpleJoinScreen();
|
||||
CSimpleJoinScreen(CMenuScreen::EMultiMode mode);
|
||||
};
|
||||
|
||||
extern ISelectionScreenInfo *SEL;
|
||||
|
@ -53,11 +53,7 @@ CVideoPlayer::CVideoPlayer()
|
||||
frame = nullptr;
|
||||
codec = nullptr;
|
||||
sws = nullptr;
|
||||
#ifdef VCMI_SDL1
|
||||
overlay = nullptr;
|
||||
#else
|
||||
texture = nullptr;
|
||||
#endif
|
||||
dest = nullptr;
|
||||
context = nullptr;
|
||||
|
||||
@ -108,11 +104,7 @@ bool CVideoPlayer::open(std::string fname, bool loop, bool useOverlay, bool scal
|
||||
return false;
|
||||
}
|
||||
// Retrieve stream information
|
||||
#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(53, 17, 0)
|
||||
if (av_find_stream_info(format) < 0)
|
||||
#else
|
||||
if (avformat_find_stream_info(format, nullptr) < 0)
|
||||
#endif
|
||||
return false;
|
||||
|
||||
// Find the first video stream
|
||||
@ -143,22 +135,16 @@ bool CVideoPlayer::open(std::string fname, bool loop, bool useOverlay, bool scal
|
||||
}
|
||||
|
||||
// Open codec
|
||||
#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(53, 6, 0)
|
||||
if ( avcodec_open(codecContext, codec) < 0 )
|
||||
#else
|
||||
if ( avcodec_open2(codecContext, codec, nullptr) < 0 )
|
||||
#endif
|
||||
{
|
||||
// Could not open codec
|
||||
codec = nullptr;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Allocate video frame
|
||||
frame = avcodec_alloc_frame();
|
||||
frame = av_frame_alloc();
|
||||
|
||||
//setup scaling
|
||||
|
||||
if(scale)
|
||||
{
|
||||
pos.w = screen->w;
|
||||
@ -173,13 +159,7 @@ bool CVideoPlayer::open(std::string fname, bool loop, bool useOverlay, bool scal
|
||||
// Allocate a place to put our YUV image on that screen
|
||||
if (useOverlay)
|
||||
{
|
||||
#ifdef VCMI_SDL1
|
||||
overlay = SDL_CreateYUVOverlay(pos.w, pos.h,
|
||||
SDL_YV12_OVERLAY, screen);
|
||||
#else
|
||||
texture = SDL_CreateTexture( mainRenderer, SDL_PIXELFORMAT_IYUV, SDL_TEXTUREACCESS_STATIC, pos.w, pos.h);
|
||||
#endif
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -188,34 +168,28 @@ bool CVideoPlayer::open(std::string fname, bool loop, bool useOverlay, bool scal
|
||||
destRect.w = pos.w;
|
||||
destRect.h = pos.h;
|
||||
}
|
||||
#ifdef VCMI_SDL1
|
||||
if (overlay == nullptr && dest == nullptr)
|
||||
return false;
|
||||
|
||||
if (overlay)
|
||||
#else
|
||||
if (texture == nullptr && dest == nullptr)
|
||||
return false;
|
||||
|
||||
if (texture)
|
||||
#endif
|
||||
{ // Convert the image into YUV format that SDL uses
|
||||
sws = sws_getContext(codecContext->width, codecContext->height, codecContext->pix_fmt,
|
||||
pos.w, pos.h, PIX_FMT_YUV420P,
|
||||
pos.w, pos.h,
|
||||
AV_PIX_FMT_YUV420P,
|
||||
SWS_BICUBIC, nullptr, nullptr, nullptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
PixelFormat screenFormat = PIX_FMT_NONE;
|
||||
AVPixelFormat screenFormat = AV_PIX_FMT_NONE;
|
||||
if (screen->format->Bshift > screen->format->Rshift)
|
||||
{
|
||||
// this a BGR surface
|
||||
switch (screen->format->BytesPerPixel)
|
||||
{
|
||||
case 2: screenFormat = PIX_FMT_BGR565; break;
|
||||
case 3: screenFormat = PIX_FMT_BGR24; break;
|
||||
case 4: screenFormat = PIX_FMT_BGR32; break;
|
||||
case 2: screenFormat = AV_PIX_FMT_BGR565; break;
|
||||
case 3: screenFormat = AV_PIX_FMT_BGR24; break;
|
||||
case 4: screenFormat = AV_PIX_FMT_BGR32; break;
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
@ -224,9 +198,9 @@ bool CVideoPlayer::open(std::string fname, bool loop, bool useOverlay, bool scal
|
||||
// this a RGB surface
|
||||
switch (screen->format->BytesPerPixel)
|
||||
{
|
||||
case 2: screenFormat = PIX_FMT_RGB565; break;
|
||||
case 3: screenFormat = PIX_FMT_RGB24; break;
|
||||
case 4: screenFormat = PIX_FMT_RGB32; break;
|
||||
case 2: screenFormat = AV_PIX_FMT_RGB565; break;
|
||||
case 3: screenFormat = AV_PIX_FMT_RGB24; break;
|
||||
case 4: screenFormat = AV_PIX_FMT_RGB32; break;
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
@ -284,23 +258,6 @@ bool CVideoPlayer::nextFrame()
|
||||
{
|
||||
AVPicture pict;
|
||||
|
||||
#ifdef VCMI_SDL1
|
||||
if (overlay) {
|
||||
SDL_LockYUVOverlay(overlay);
|
||||
|
||||
pict.data[0] = overlay->pixels[0];
|
||||
pict.data[1] = overlay->pixels[2];
|
||||
pict.data[2] = overlay->pixels[1];
|
||||
|
||||
pict.linesize[0] = overlay->pitches[0];
|
||||
pict.linesize[1] = overlay->pitches[2];
|
||||
pict.linesize[2] = overlay->pitches[1];
|
||||
|
||||
sws_scale(sws, frame->data, frame->linesize,
|
||||
0, codecContext->height, pict.data, pict.linesize);
|
||||
|
||||
SDL_UnlockYUVOverlay(overlay);
|
||||
#else
|
||||
if (texture) {
|
||||
avpicture_alloc(&pict, AV_PIX_FMT_YUV420P, pos.w, pos.h);
|
||||
|
||||
@ -311,7 +268,6 @@ bool CVideoPlayer::nextFrame()
|
||||
pict.data[1], pict.linesize[1],
|
||||
pict.data[2], pict.linesize[2]);
|
||||
avpicture_free(&pict);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -387,22 +343,12 @@ void CVideoPlayer::close()
|
||||
sws = nullptr;
|
||||
}
|
||||
|
||||
#ifdef VCMI_SDL1
|
||||
if (overlay)
|
||||
{
|
||||
SDL_FreeYUVOverlay(overlay);
|
||||
overlay = nullptr;
|
||||
}
|
||||
#else
|
||||
if (texture)
|
||||
{
|
||||
SDL_DestroyTexture(texture);
|
||||
texture = nullptr;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
if (dest)
|
||||
{
|
||||
SDL_FreeSurface(dest);
|
||||
@ -411,8 +357,7 @@ void CVideoPlayer::close()
|
||||
|
||||
if (frame)
|
||||
{
|
||||
av_free(frame);
|
||||
frame = nullptr;
|
||||
av_frame_free(&frame);//will be set to null
|
||||
}
|
||||
|
||||
if (codec)
|
||||
@ -424,12 +369,7 @@ void CVideoPlayer::close()
|
||||
|
||||
if (format)
|
||||
{
|
||||
#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(53, 17, 0)
|
||||
av_close_input_file(format);
|
||||
format = nullptr;
|
||||
#else
|
||||
avformat_close_input(&format);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (context)
|
||||
@ -455,13 +395,8 @@ bool CVideoPlayer::playVideo(int x, int y, SDL_Surface *dst, bool stopOnKey)
|
||||
if(stopOnKey && keyDown())
|
||||
return false;
|
||||
|
||||
#ifdef VCMI_SDL1
|
||||
SDL_DisplayYUVOverlay(overlay, &pos);
|
||||
#else
|
||||
SDL_RenderCopy(mainRenderer, texture, NULL, &pos);
|
||||
SDL_RenderPresent(mainRenderer);
|
||||
#endif
|
||||
|
||||
|
||||
// Wait 3 frames
|
||||
GH.mainFPSmng->framerateDelay();
|
||||
|
@ -47,45 +47,53 @@ public:
|
||||
|
||||
#include <SDL.h>
|
||||
#include <SDL_video.h>
|
||||
#if SDL_VERSION_ATLEAST(1,3,0) && !SDL_VERSION_ATLEAST(2,0,0)
|
||||
#include <SDL_compat.h>
|
||||
#endif
|
||||
|
||||
extern "C" {
|
||||
#include <libavformat/avformat.h>
|
||||
#include <libswscale/swscale.h>
|
||||
|
||||
// compatibility with different versions od libavutil
|
||||
#if (LIBAVUTIL_VERSION_INT < AV_VERSION_INT(51, 42, 0)) || \
|
||||
(LIBAVUTIL_VERSION_INT == AV_VERSION_INT(51, 73, 101))
|
||||
|
||||
#define AV_PIX_FMT_NONE PIX_FMT_NONE
|
||||
#define AV_PIX_FMT_NV12 PIX_FMT_NV12
|
||||
#define AV_PIX_FMT_YUV420P PIX_FMT_YUV420P
|
||||
#define AV_PIX_FMT_UYVY422 PIX_FMT_UYVY422
|
||||
#define AV_PIX_FMT_YUYV422 PIX_FMT_YUYV422
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
//compatibility for libav 9.18 in ubuntu 14.04, 52.66.100 is ffmpeg 2.2.3
|
||||
#if (LIBAVUTIL_VERSION_INT < AV_VERSION_INT(52, 66, 100))
|
||||
inline AVFrame * av_frame_alloc()
|
||||
{
|
||||
return avcodec_alloc_frame();
|
||||
}
|
||||
|
||||
inline void av_frame_free(AVFrame ** frame)
|
||||
{
|
||||
av_free(*frame);
|
||||
*frame = nullptr;
|
||||
}
|
||||
#endif // VCMI_USE_OLD_AVUTIL
|
||||
|
||||
//fix for travis-ci
|
||||
#if (LIBAVUTIL_VERSION_INT < AV_VERSION_INT(52, 0, 0))
|
||||
#define AVPixelFormat PixelFormat
|
||||
#define AV_PIX_FMT_NONE PIX_FMT_NONE
|
||||
#define AV_PIX_FMT_YUV420P PIX_FMT_YUV420P
|
||||
#define AV_PIX_FMT_BGR565 PIX_FMT_BGR565
|
||||
#define AV_PIX_FMT_BGR24 PIX_FMT_BGR24
|
||||
#define AV_PIX_FMT_BGR32 PIX_FMT_BGR32
|
||||
#define AV_PIX_FMT_RGB565 PIX_FMT_RGB565
|
||||
#define AV_PIX_FMT_RGB24 PIX_FMT_RGB24
|
||||
#define AV_PIX_FMT_RGB32 PIX_FMT_RGB32
|
||||
#endif
|
||||
|
||||
class CVideoPlayer : public IMainVideoPlayer
|
||||
{
|
||||
int stream; // stream index in video
|
||||
AVFormatContext *format;
|
||||
AVCodecContext *codecContext; // codec context for stream
|
||||
AVCodec *codec;
|
||||
AVFrame *frame;
|
||||
AVFrame *frame;
|
||||
struct SwsContext *sws;
|
||||
|
||||
AVIOContext * context;
|
||||
|
||||
// Destination. Either overlay or dest.
|
||||
#ifdef VCMI_SDL1
|
||||
SDL_Overlay * overlay;
|
||||
#else
|
||||
SDL_Texture *texture;
|
||||
#endif
|
||||
|
||||
SDL_Texture *texture;
|
||||
SDL_Surface *dest;
|
||||
SDL_Rect destRect; // valid when dest is used
|
||||
SDL_Rect pos; // destination on screen
|
||||
@ -109,7 +117,7 @@ public:
|
||||
void show(int x, int y, SDL_Surface *dst, bool update = true) override; //blit current frame
|
||||
void redraw(int x, int y, SDL_Surface *dst, bool update = true) override; //reblits buffer
|
||||
void update(int x, int y, SDL_Surface *dst, bool forceRedraw, bool update = true) override; //moves to next frame if appropriate, and blits it or blits only if redraw parameter is set true
|
||||
|
||||
|
||||
// Opens video, calls playVideo, closes video; returns playVideo result (if whole video has been played)
|
||||
bool openAndPlayVideo(std::string name, int x, int y, SDL_Surface *dst, bool stopOnKey = false, bool scale = false) override;
|
||||
|
||||
|
@ -19,7 +19,9 @@
|
||||
#include "../lib/CTownHandler.h"
|
||||
#include "../lib/CBuildingHandler.h"
|
||||
#include "../lib/spells/CSpellHandler.h"
|
||||
#include "../lib/Connection.h"
|
||||
#include "../lib/serializer/CTypeList.h"
|
||||
#include "../lib/serializer/Connection.h"
|
||||
#include "../lib/serializer/CLoadIntegrityValidator.h"
|
||||
#ifndef VCMI_ANDROID
|
||||
#include "../lib/Interprocess.h"
|
||||
#endif
|
||||
@ -30,7 +32,6 @@
|
||||
#include "../lib/JsonNode.h"
|
||||
#include "mapHandler.h"
|
||||
#include "../lib/CConfigHandler.h"
|
||||
#include "Client.h"
|
||||
#include "CPreGame.h"
|
||||
#include "battle/CBattleInterface.h"
|
||||
#include "../lib/CThreadHelper.h"
|
||||
@ -59,8 +60,8 @@ template <typename T> class CApplyOnCL;
|
||||
class CBaseForCLApply
|
||||
{
|
||||
public:
|
||||
virtual void applyOnClAfter(CClient *cl, void *pack) const =0;
|
||||
virtual void applyOnClBefore(CClient *cl, void *pack) const =0;
|
||||
virtual void applyOnClAfter(CClient *cl, void *pack) const =0;
|
||||
virtual void applyOnClBefore(CClient *cl, void *pack) const =0;
|
||||
virtual ~CBaseForCLApply(){}
|
||||
|
||||
template<typename U> static CBaseForCLApply *getApplier(const U * t=nullptr)
|
||||
@ -72,12 +73,12 @@ public:
|
||||
template <typename T> class CApplyOnCL : public CBaseForCLApply
|
||||
{
|
||||
public:
|
||||
void applyOnClAfter(CClient *cl, void *pack) const
|
||||
void applyOnClAfter(CClient *cl, void *pack) const override
|
||||
{
|
||||
T *ptr = static_cast<T*>(pack);
|
||||
ptr->applyCl(cl);
|
||||
}
|
||||
void applyOnClBefore(CClient *cl, void *pack) const
|
||||
void applyOnClBefore(CClient *cl, void *pack) const override
|
||||
{
|
||||
T *ptr = static_cast<T*>(pack);
|
||||
ptr->applyFirstCl(cl);
|
||||
@ -87,12 +88,12 @@ public:
|
||||
template <> class CApplyOnCL<CPack> : public CBaseForCLApply
|
||||
{
|
||||
public:
|
||||
void applyOnClAfter(CClient *cl, void *pack) const
|
||||
void applyOnClAfter(CClient *cl, void *pack) const override
|
||||
{
|
||||
logGlobal->errorStream() << "Cannot apply on CL plain CPack!";
|
||||
assert(0);
|
||||
}
|
||||
void applyOnClBefore(CClient *cl, void *pack) const
|
||||
void applyOnClBefore(CClient *cl, void *pack) const override
|
||||
{
|
||||
logGlobal->errorStream() << "Cannot apply on CL plain CPack!";
|
||||
assert(0);
|
||||
@ -140,14 +141,17 @@ void CClient::waitForMoveAndSend(PlayerColor color)
|
||||
setThreadName("CClient::waitForMoveAndSend");
|
||||
assert(vstd::contains(battleints, color));
|
||||
BattleAction ba = battleints[color]->activeStack(gs->curB->battleGetStackByID(gs->curB->activeStack, false));
|
||||
logNetwork->traceStream() << "Send battle action to server: " << ba;
|
||||
MakeAction temp_action(ba);
|
||||
sendRequest(&temp_action, color);
|
||||
if(ba.actionType != Battle::CANCEL)
|
||||
{
|
||||
logNetwork->traceStream() << "Send battle action to server: " << ba;
|
||||
MakeAction temp_action(ba);
|
||||
sendRequest(&temp_action, color);
|
||||
}
|
||||
return;
|
||||
}
|
||||
catch(boost::thread_interrupted&)
|
||||
{
|
||||
logNetwork->debugStream() << "Wait for move thread was interrupted and no action will be send. Was a battle ended by spell?";
|
||||
logNetwork->debugStream() << "Wait for move thread was interrupted and no action will be send. Was a battle ended by spell?";
|
||||
return;
|
||||
}
|
||||
catch(...)
|
||||
@ -155,7 +159,7 @@ void CClient::waitForMoveAndSend(PlayerColor color)
|
||||
handleException();
|
||||
return;
|
||||
}
|
||||
logNetwork->errorStream() << "We should not be here!";
|
||||
logNetwork->errorStream() << "We should not be here!";
|
||||
}
|
||||
|
||||
void CClient::run()
|
||||
@ -166,8 +170,8 @@ void CClient::run()
|
||||
while(!terminate)
|
||||
{
|
||||
CPack *pack = serv->retreivePack(); //get the package from the server
|
||||
|
||||
if (terminate)
|
||||
|
||||
if (terminate)
|
||||
{
|
||||
vstd::clear_pointer(pack);
|
||||
break;
|
||||
@ -175,15 +179,15 @@ void CClient::run()
|
||||
|
||||
handlePack(pack);
|
||||
}
|
||||
}
|
||||
}
|
||||
//catch only asio exceptions
|
||||
catch (const boost::system::system_error& e)
|
||||
{
|
||||
logNetwork->errorStream() << "Lost connection to server, ending listening thread!";
|
||||
logNetwork->errorStream() << e.what();
|
||||
{
|
||||
logNetwork->errorStream() << "Lost connection to server, ending listening thread!";
|
||||
logNetwork->errorStream() << e.what();
|
||||
if(!terminate) //rethrow (-> boom!) only if closing connection was unexpected
|
||||
{
|
||||
logNetwork->errorStream() << "Something wrong, lost connection while game is still ongoing...";
|
||||
logNetwork->errorStream() << "Something wrong, lost connection while game is still ongoing...";
|
||||
throw;
|
||||
}
|
||||
}
|
||||
@ -193,7 +197,7 @@ void CClient::save(const std::string & fname)
|
||||
{
|
||||
if(gs->curB)
|
||||
{
|
||||
logNetwork->errorStream() << "Game cannot be saved during battle!";
|
||||
logNetwork->errorStream() << "Game cannot be saved during battle!";
|
||||
return;
|
||||
}
|
||||
|
||||
@ -201,33 +205,35 @@ void CClient::save(const std::string & fname)
|
||||
sendRequest((CPackForClient*)&save_game, PlayerColor::NEUTRAL);
|
||||
}
|
||||
|
||||
void CClient::endGame( bool closeConnection /*= true*/ )
|
||||
void CClient::endGame(bool closeConnection /*= true*/)
|
||||
{
|
||||
//suggest interfaces to finish their stuff (AI should interrupt any bg working threads)
|
||||
for(auto i : playerint)
|
||||
for (auto& i : playerint)
|
||||
i.second->finish();
|
||||
|
||||
// Game is ending
|
||||
// Tell the network thread to reach a stable state
|
||||
if(closeConnection)
|
||||
if (closeConnection)
|
||||
stopConnection();
|
||||
logNetwork->infoStream() << "Closed connection.";
|
||||
logNetwork->infoStream() << "Closed connection.";
|
||||
|
||||
GH.curInt = nullptr;
|
||||
{
|
||||
boost::unique_lock<boost::recursive_mutex> un(*LOCPLINT->pim);
|
||||
logNetwork->infoStream() << "Ending current game!";
|
||||
logNetwork->infoStream() << "Ending current game!";
|
||||
if(GH.topInt())
|
||||
{
|
||||
GH.topInt()->deactivate();
|
||||
}
|
||||
GH.listInt.clear();
|
||||
GH.objsToBlit.clear();
|
||||
GH.statusbar = nullptr;
|
||||
logNetwork->infoStream() << "Removed GUI.";
|
||||
logNetwork->infoStream() << "Removed GUI.";
|
||||
|
||||
vstd::clear_pointer(const_cast<CGameInfo*>(CGI)->mh);
|
||||
vstd::clear_pointer(gs);
|
||||
|
||||
logNetwork->infoStream() << "Deleted mapHandler and gameState.";
|
||||
logNetwork->infoStream() << "Deleted mapHandler and gameState.";
|
||||
LOCPLINT = nullptr;
|
||||
}
|
||||
|
||||
@ -235,30 +241,39 @@ void CClient::endGame( bool closeConnection /*= true*/ )
|
||||
battleints.clear();
|
||||
callbacks.clear();
|
||||
battleCallbacks.clear();
|
||||
logNetwork->infoStream() << "Deleted playerInts.";
|
||||
|
||||
logNetwork->infoStream() << "Client stopped.";
|
||||
CGKeys::reset();
|
||||
CGMagi::reset();
|
||||
CGObelisk::reset();
|
||||
logNetwork->infoStream() << "Deleted playerInts.";
|
||||
logNetwork->infoStream() << "Client stopped.";
|
||||
}
|
||||
|
||||
#if 1
|
||||
void CClient::loadGame(const std::string & fname, const bool server, const std::vector<int>& humanplayerindices, const int loadNumPlayers, int player_, const std::string & ipaddr, const std::string & port)
|
||||
{
|
||||
PlayerColor player(player_); //intentional shadowing
|
||||
PlayerColor player(player_); //intentional shadowing
|
||||
logNetwork->infoStream() << "Loading procedure started!";
|
||||
|
||||
logNetwork->infoStream() <<"Loading procedure started!";
|
||||
std::string realPort;
|
||||
if(settings["testing"]["enabled"].Bool())
|
||||
realPort = settings["testing"]["port"].String();
|
||||
else if(port.size())
|
||||
realPort = port;
|
||||
else
|
||||
realPort = boost::lexical_cast<std::string>(settings["server"]["port"].Float());
|
||||
|
||||
CServerHandler sh;
|
||||
if(server)
|
||||
sh.startServer();
|
||||
else
|
||||
serv = sh.justConnectToServer(ipaddr,port=="" ? "3030" : port);
|
||||
if(server)
|
||||
sh.startServer();
|
||||
else
|
||||
serv = sh.justConnectToServer(ipaddr, realPort);
|
||||
|
||||
CStopWatch tmh;
|
||||
unique_ptr<CLoadFile> loader;
|
||||
std::unique_ptr<CLoadFile> loader;
|
||||
try
|
||||
{
|
||||
std::string clientSaveName = *CResourceHandler::get("local")->getResourceName(ResourceID(fname, EResType::CLIENT_SAVEGAME));
|
||||
std::string controlServerSaveName;
|
||||
boost::filesystem::path clientSaveName = *CResourceHandler::get("local")->getResourceName(ResourceID(fname, EResType::CLIENT_SAVEGAME));
|
||||
boost::filesystem::path controlServerSaveName;
|
||||
|
||||
if (CResourceHandler::get("local")->existsResource(ResourceID(fname, EResType::SERVER_SAVEGAME)))
|
||||
{
|
||||
@ -266,26 +281,26 @@ void CClient::loadGame(const std::string & fname, const bool server, const std::
|
||||
}
|
||||
else// create entry for server savegame. Triggered if save was made after launch and not yet present in res handler
|
||||
{
|
||||
controlServerSaveName = clientSaveName.substr(0, clientSaveName.find_last_of(".")) + ".vsgm1";
|
||||
CResourceHandler::get("local")->createResource(controlServerSaveName, true);
|
||||
controlServerSaveName = boost::filesystem::path(clientSaveName).replace_extension(".vsgm1");
|
||||
CResourceHandler::get("local")->createResource(controlServerSaveName.string(), true);
|
||||
}
|
||||
|
||||
if(clientSaveName.empty())
|
||||
throw std::runtime_error("Cannot open client part of " + fname);
|
||||
if(controlServerSaveName.empty())
|
||||
if(controlServerSaveName.empty() || !boost::filesystem::exists(controlServerSaveName))
|
||||
throw std::runtime_error("Cannot open server part of " + fname);
|
||||
|
||||
{
|
||||
CLoadIntegrityValidator checkingLoader(clientSaveName, controlServerSaveName, minSupportedVersion);
|
||||
CLoadIntegrityValidator checkingLoader(clientSaveName, controlServerSaveName, MINIMAL_SERIALIZATION_VERSION);
|
||||
loadCommonState(checkingLoader);
|
||||
loader = checkingLoader.decay();
|
||||
}
|
||||
logNetwork->infoStream() << "Loaded common part of save " << tmh.getDiff();
|
||||
logNetwork->infoStream() << "Loaded common part of save " << tmh.getDiff();
|
||||
const_cast<CGameInfo*>(CGI)->mh = new CMapHandler();
|
||||
const_cast<CGameInfo*>(CGI)->mh->map = gs->map;
|
||||
pathInfo = make_unique<CPathsInfo>(getMapSize());
|
||||
CGI->mh->init();
|
||||
logNetwork->infoStream() <<"Initing maphandler: "<<tmh.getDiff();
|
||||
logNetwork->infoStream() <<"Initing maphandler: "<<tmh.getDiff();
|
||||
}
|
||||
catch(std::exception &e)
|
||||
{
|
||||
@ -298,53 +313,53 @@ void CClient::loadGame(const std::string & fname, const bool server, const std::
|
||||
player = PlayerColor(player_);
|
||||
*/
|
||||
|
||||
std::set<PlayerColor> clientPlayers;
|
||||
if(server)
|
||||
serv = sh.connectToServer();
|
||||
std::set<PlayerColor> clientPlayers;
|
||||
if(server)
|
||||
serv = sh.connectToServer();
|
||||
//*loader >> *this;
|
||||
|
||||
if(server)
|
||||
{
|
||||
tmh.update();
|
||||
ui8 pom8;
|
||||
*serv << ui8(3) << ui8(loadNumPlayers); //load game; one client if single-player
|
||||
*serv << fname;
|
||||
*serv >> pom8;
|
||||
if(pom8)
|
||||
throw std::runtime_error("Server cannot open the savegame!");
|
||||
else
|
||||
logNetwork->infoStream() << "Server opened savegame properly.";
|
||||
}
|
||||
if(server)
|
||||
{
|
||||
tmh.update();
|
||||
ui8 pom8;
|
||||
*serv << ui8(3) << ui8(loadNumPlayers); //load game; one client if single-player
|
||||
*serv << fname;
|
||||
*serv >> pom8;
|
||||
if(pom8)
|
||||
throw std::runtime_error("Server cannot open the savegame!");
|
||||
else
|
||||
logNetwork->infoStream() << "Server opened savegame properly.";
|
||||
}
|
||||
|
||||
if(server)
|
||||
{
|
||||
for(auto & elem : gs->scenarioOps->playerInfos)
|
||||
if(!std::count(humanplayerindices.begin(),humanplayerindices.end(),elem.first.getNum()) || elem.first==player)
|
||||
{
|
||||
clientPlayers.insert(elem.first);
|
||||
}
|
||||
clientPlayers.insert(PlayerColor::NEUTRAL);
|
||||
}
|
||||
else
|
||||
{
|
||||
clientPlayers.insert(player);
|
||||
}
|
||||
if(server)
|
||||
{
|
||||
for(auto & elem : gs->scenarioOps->playerInfos)
|
||||
{
|
||||
if(!std::count(humanplayerindices.begin(),humanplayerindices.end(),elem.first.getNum()) || elem.first==player)
|
||||
clientPlayers.insert(elem.first);
|
||||
}
|
||||
clientPlayers.insert(PlayerColor::NEUTRAL);
|
||||
}
|
||||
else
|
||||
{
|
||||
clientPlayers.insert(player);
|
||||
}
|
||||
|
||||
std::cout << "CLIENTPLAYERS:\n";
|
||||
for(auto x : clientPlayers)
|
||||
std::cout << x << std::endl;
|
||||
std::cout << "ENDCLIENTPLAYERS\n";
|
||||
std::cout << "CLIENTPLAYERS:\n";
|
||||
for(auto x : clientPlayers)
|
||||
std::cout << x << std::endl;
|
||||
std::cout << "ENDCLIENTPLAYERS\n";
|
||||
|
||||
serialize(loader->serializer,0,clientPlayers);
|
||||
*serv << ui32(clientPlayers.size());
|
||||
for(auto & elem : clientPlayers)
|
||||
*serv << ui8(elem.getNum());
|
||||
serv->addStdVecItems(gs); /*why is this here?*/
|
||||
serialize(loader->serializer,0,clientPlayers);
|
||||
*serv << ui32(clientPlayers.size());
|
||||
for(auto & elem : clientPlayers)
|
||||
*serv << ui8(elem.getNum());
|
||||
serv->addStdVecItems(gs); /*why is this here?*/
|
||||
|
||||
//*loader >> *this;
|
||||
logNetwork->infoStream() << "Loaded client part of save " << tmh.getDiff();
|
||||
logNetwork->infoStream() << "Loaded client part of save " << tmh.getDiff();
|
||||
|
||||
logNetwork->infoStream() <<"Sent info to server: "<<tmh.getDiff();
|
||||
logNetwork->infoStream() <<"Sent info to server: "<<tmh.getDiff();
|
||||
|
||||
//*serv << clientPlayers;
|
||||
serv->enableStackSendingByID();
|
||||
@ -366,7 +381,7 @@ void CClient::newGame( CConnection *con, StartInfo *si )
|
||||
{
|
||||
enum {SINGLE, HOST, GUEST} networkMode = SINGLE;
|
||||
|
||||
if (con == nullptr)
|
||||
if (con == nullptr)
|
||||
{
|
||||
CServerHandler sh;
|
||||
serv = sh.connectToServer();
|
||||
@ -393,7 +408,7 @@ void CClient::newGame( CConnection *con, StartInfo *si )
|
||||
}
|
||||
|
||||
c >> si;
|
||||
logNetwork->infoStream() <<"\tSending/Getting info to/from the server: "<<tmh.getDiff();
|
||||
logNetwork->infoStream() <<"\tSending/Getting info to/from the server: "<<tmh.getDiff();
|
||||
c.enableStackSendingByID();
|
||||
c.disableSmartPointerSerialization();
|
||||
|
||||
@ -403,7 +418,7 @@ void CClient::newGame( CConnection *con, StartInfo *si )
|
||||
|
||||
gs->scenarioOps = si;
|
||||
gs->init(si);
|
||||
logNetwork->infoStream() <<"Initializing GameState (together): "<<tmh.getDiff();
|
||||
logNetwork->infoStream() <<"Initializing GameState (together): "<<tmh.getDiff();
|
||||
|
||||
// Now after possible random map gen, we know exact player count.
|
||||
// Inform server about how many players client handles
|
||||
@ -426,10 +441,10 @@ void CClient::newGame( CConnection *con, StartInfo *si )
|
||||
{
|
||||
const_cast<CGameInfo*>(CGI)->mh = new CMapHandler();
|
||||
CGI->mh->map = gs->map;
|
||||
logNetwork->infoStream() <<"Creating mapHandler: "<<tmh.getDiff();
|
||||
logNetwork->infoStream() << "Creating mapHandler: " << tmh.getDiff();
|
||||
CGI->mh->init();
|
||||
pathInfo = make_unique<CPathsInfo>(getMapSize());
|
||||
logNetwork->infoStream() <<"Initializing mapHandler (together): "<<tmh.getDiff();
|
||||
logNetwork->infoStream() << "Initializing mapHandler (together): " << tmh.getDiff();
|
||||
}
|
||||
|
||||
int humanPlayers = 0;
|
||||
@ -440,7 +455,7 @@ void CClient::newGame( CConnection *con, StartInfo *si )
|
||||
if(!vstd::contains(myPlayers, color))
|
||||
continue;
|
||||
|
||||
logNetwork->traceStream() << "Preparing interface for player " << color;
|
||||
logNetwork->traceStream() << "Preparing interface for player " << color;
|
||||
if(si->mode != StartInfo::DUEL)
|
||||
{
|
||||
if(elem.second.playerID == PlayerSettings::PLAYER_AI)
|
||||
@ -449,9 +464,9 @@ void CClient::newGame( CConnection *con, StartInfo *si )
|
||||
logNetwork->infoStream() << boost::format("Player %s will be lead by %s") % color % AiToGive;
|
||||
installNewPlayerInterface(CDynLibHandler::getNewAI(AiToGive), color);
|
||||
}
|
||||
else
|
||||
else
|
||||
{
|
||||
installNewPlayerInterface(make_shared<CPlayerInterface>(color), color);
|
||||
installNewPlayerInterface(std::make_shared<CPlayerInterface>(color), color);
|
||||
humanPlayers++;
|
||||
}
|
||||
}
|
||||
@ -467,7 +482,7 @@ void CClient::newGame( CConnection *con, StartInfo *si )
|
||||
if(!gNoGUI)
|
||||
{
|
||||
boost::unique_lock<boost::recursive_mutex> un(*LOCPLINT->pim);
|
||||
auto p = make_shared<CPlayerInterface>(PlayerColor::NEUTRAL);
|
||||
auto p = std::make_shared<CPlayerInterface>(PlayerColor::NEUTRAL);
|
||||
p->observerInDuelMode = true;
|
||||
installNewPlayerInterface(p, boost::none);
|
||||
GH.curInt = p.get();
|
||||
@ -492,15 +507,15 @@ void CClient::newGame( CConnection *con, StartInfo *si )
|
||||
// nm->giveActionCB(this);
|
||||
// nm->giveInfoCB(this);
|
||||
// nm->init();
|
||||
//
|
||||
//
|
||||
// erm = nm; //something tells me that there'll at most one module and it'll be ERM
|
||||
// }
|
||||
}
|
||||
|
||||
void CClient::serialize(COSer & h, const int version)
|
||||
void CClient::serialize(BinarySerializer & h, const int version)
|
||||
{
|
||||
assert(h.saving);
|
||||
h & hotSeat;
|
||||
h & hotSeat;
|
||||
{
|
||||
ui8 players = playerint.size();
|
||||
h & players;
|
||||
@ -510,12 +525,12 @@ void CClient::serialize(COSer & h, const int version)
|
||||
LOG_TRACE_PARAMS(logGlobal, "Saving player %s interface", i->first);
|
||||
assert(i->first == i->second->playerID);
|
||||
h & i->first & i->second->dllName & i->second->human;
|
||||
i->second->saveGame(h, version);
|
||||
i->second->saveGame(h, version);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CClient::serialize(CISer & h, const int version)
|
||||
void CClient::serialize(BinaryDeserializer & h, const int version)
|
||||
{
|
||||
assert(!h.saving);
|
||||
h & hotSeat;
|
||||
@ -526,19 +541,19 @@ void CClient::serialize(CISer & h, const int version)
|
||||
for(int i=0; i < players; i++)
|
||||
{
|
||||
std::string dllname;
|
||||
PlayerColor pid;
|
||||
PlayerColor pid;
|
||||
bool isHuman = false;
|
||||
|
||||
h & pid & dllname & isHuman;
|
||||
LOG_TRACE_PARAMS(logGlobal, "Loading player %s interface", pid);
|
||||
|
||||
shared_ptr<CGameInterface> nInt;
|
||||
std::shared_ptr<CGameInterface> nInt;
|
||||
if(dllname.length())
|
||||
{
|
||||
if(pid == PlayerColor::NEUTRAL)
|
||||
{
|
||||
installNewBattleInterface(CDynLibHandler::getNewBattleAI(dllname), pid);
|
||||
//TODO? consider serialization
|
||||
//TODO? consider serialization
|
||||
continue;
|
||||
}
|
||||
else
|
||||
@ -550,7 +565,7 @@ void CClient::serialize(CISer & h, const int version)
|
||||
else
|
||||
{
|
||||
assert(isHuman);
|
||||
nInt = make_shared<CPlayerInterface>(pid);
|
||||
nInt = std::make_shared<CPlayerInterface>(pid);
|
||||
}
|
||||
|
||||
nInt->dllName = dllname;
|
||||
@ -566,7 +581,7 @@ void CClient::serialize(CISer & h, const int version)
|
||||
}
|
||||
}
|
||||
|
||||
void CClient::serialize(COSer & h, const int version, const std::set<PlayerColor> & playerIDs)
|
||||
void CClient::serialize(BinarySerializer & h, const int version, const std::set<PlayerColor> & playerIDs)
|
||||
{
|
||||
assert(h.saving);
|
||||
h & hotSeat;
|
||||
@ -579,12 +594,12 @@ void CClient::serialize(COSer & h, const int version, const std::set<PlayerColor
|
||||
LOG_TRACE_PARAMS(logGlobal, "Saving player %s interface", i->first);
|
||||
assert(i->first == i->second->playerID);
|
||||
h & i->first & i->second->dllName & i->second->human;
|
||||
i->second->saveGame(h, version);
|
||||
i->second->saveGame(h, version);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CClient::serialize(CISer & h, const int version, const std::set<PlayerColor> & playerIDs)
|
||||
void CClient::serialize(BinaryDeserializer & h, const int version, const std::set<PlayerColor> & playerIDs)
|
||||
{
|
||||
assert(!h.saving);
|
||||
h & hotSeat;
|
||||
@ -595,20 +610,20 @@ void CClient::serialize(CISer & h, const int version, const std::set<PlayerColor
|
||||
for(int i=0; i < players; i++)
|
||||
{
|
||||
std::string dllname;
|
||||
PlayerColor pid;
|
||||
PlayerColor pid;
|
||||
bool isHuman = false;
|
||||
|
||||
h & pid & dllname & isHuman;
|
||||
LOG_TRACE_PARAMS(logGlobal, "Loading player %s interface", pid);
|
||||
|
||||
shared_ptr<CGameInterface> nInt;
|
||||
std::shared_ptr<CGameInterface> nInt;
|
||||
if(dllname.length())
|
||||
{
|
||||
if(pid == PlayerColor::NEUTRAL)
|
||||
{
|
||||
if(playerIDs.count(pid))
|
||||
installNewBattleInterface(CDynLibHandler::getNewBattleAI(dllname), pid);
|
||||
//TODO? consider serialization
|
||||
if(playerIDs.count(pid))
|
||||
installNewBattleInterface(CDynLibHandler::getNewBattleAI(dllname), pid);
|
||||
//TODO? consider serialization
|
||||
continue;
|
||||
}
|
||||
else
|
||||
@ -620,49 +635,55 @@ void CClient::serialize(CISer & h, const int version, const std::set<PlayerColor
|
||||
else
|
||||
{
|
||||
assert(isHuman);
|
||||
nInt = make_shared<CPlayerInterface>(pid);
|
||||
nInt = std::make_shared<CPlayerInterface>(pid);
|
||||
}
|
||||
|
||||
nInt->dllName = dllname;
|
||||
nInt->human = isHuman;
|
||||
nInt->playerID = pid;
|
||||
|
||||
if(playerIDs.count(pid))
|
||||
installNewPlayerInterface(nInt, pid);
|
||||
if(playerIDs.count(pid))
|
||||
installNewPlayerInterface(nInt, pid);
|
||||
|
||||
nInt->loadGame(h, version);
|
||||
nInt->loadGame(h, version);
|
||||
}
|
||||
|
||||
if(playerIDs.count(PlayerColor::NEUTRAL))
|
||||
loadNeutralBattleAI();
|
||||
loadNeutralBattleAI();
|
||||
}
|
||||
}
|
||||
|
||||
void CClient::handlePack( CPack * pack )
|
||||
{
|
||||
CBaseForCLApply *apply = applier->apps[typeList.getTypeID(pack)]; //find the applier
|
||||
if(pack == nullptr)
|
||||
{
|
||||
logNetwork->error("Dropping nullptr CPack! You should check whether client and server ABI matches.");
|
||||
return;
|
||||
}
|
||||
CBaseForCLApply *apply = applier->getApplier(typeList.getTypeID(pack)); //find the applier
|
||||
if(apply)
|
||||
{
|
||||
boost::unique_lock<boost::recursive_mutex> guiLock(*LOCPLINT->pim);
|
||||
apply->applyOnClBefore(this,pack);
|
||||
logNetwork->traceStream() << "\tMade first apply on cl";
|
||||
apply->applyOnClBefore(this, pack);
|
||||
logNetwork->trace("\tMade first apply on cl");
|
||||
gs->apply(pack);
|
||||
logNetwork->traceStream() << "\tApplied on gs";
|
||||
apply->applyOnClAfter(this,pack);
|
||||
logNetwork->traceStream() << "\tMade second apply on cl";
|
||||
logNetwork->trace("\tApplied on gs");
|
||||
apply->applyOnClAfter(this, pack);
|
||||
logNetwork->trace("\tMade second apply on cl");
|
||||
}
|
||||
else
|
||||
{
|
||||
logNetwork->errorStream() << "Message cannot be applied, cannot find applier! TypeID " << typeList.getTypeID(pack);
|
||||
logNetwork->error("Message cannot be applied, cannot find applier! type %d - %s",
|
||||
pack->type, typeList.getTypeInfo(pack)->name());
|
||||
}
|
||||
delete pack;
|
||||
}
|
||||
|
||||
void CClient::finishCampaign( shared_ptr<CCampaignState> camp )
|
||||
void CClient::finishCampaign( std::shared_ptr<CCampaignState> camp )
|
||||
{
|
||||
}
|
||||
|
||||
void CClient::proposeNextMission(shared_ptr<CCampaignState> camp)
|
||||
void CClient::proposeNextMission(std::shared_ptr<CCampaignState> camp)
|
||||
{
|
||||
GH.pushInt(new CBonusSelection(camp));
|
||||
}
|
||||
@ -673,11 +694,11 @@ void CClient::stopConnection()
|
||||
|
||||
if (serv) //request closing connection
|
||||
{
|
||||
logNetwork->infoStream() << "Connection has been requested to be closed.";
|
||||
logNetwork->infoStream() << "Connection has been requested to be closed.";
|
||||
boost::unique_lock<boost::mutex>(*serv->wmx);
|
||||
CloseServer close_server;
|
||||
sendRequest(&close_server, PlayerColor::NEUTRAL);
|
||||
logNetwork->infoStream() << "Sent closing signal to the server";
|
||||
logNetwork->infoStream() << "Sent closing signal to the server";
|
||||
}
|
||||
|
||||
if(connectionHandler)//end connection handler
|
||||
@ -685,7 +706,7 @@ void CClient::stopConnection()
|
||||
if(connectionHandler->get_id() != boost::this_thread::get_id())
|
||||
connectionHandler->join();
|
||||
|
||||
logNetwork->infoStream() << "Connection handler thread joined";
|
||||
logNetwork->infoStream() << "Connection handler thread joined";
|
||||
|
||||
delete connectionHandler;
|
||||
connectionHandler = nullptr;
|
||||
@ -696,7 +717,7 @@ void CClient::stopConnection()
|
||||
serv->close();
|
||||
delete serv;
|
||||
serv = nullptr;
|
||||
logNetwork->warnStream() << "Our socket has been closed.";
|
||||
logNetwork->warnStream() << "Our socket has been closed.";
|
||||
}
|
||||
}
|
||||
|
||||
@ -704,7 +725,7 @@ void CClient::battleStarted(const BattleInfo * info)
|
||||
{
|
||||
for(auto &battleCb : battleCallbacks)
|
||||
{
|
||||
if(vstd::contains_if(info->sides, [&](const SideInBattle& side) {return side.color == battleCb.first; })
|
||||
if(vstd::contains_if(info->sides, [&](const SideInBattle& side) {return side.color == battleCb.first; })
|
||||
|| battleCb.first >= PlayerColor::PLAYER_LIMIT)
|
||||
{
|
||||
battleCb.second->setBattle(info);
|
||||
@ -714,7 +735,7 @@ void CClient::battleStarted(const BattleInfo * info)
|
||||
// if(battleCallbacks.count(side))
|
||||
// battleCallbacks[side]->setBattle(info);
|
||||
|
||||
shared_ptr<CPlayerInterface> att, def;
|
||||
std::shared_ptr<CPlayerInterface> att, def;
|
||||
auto &leftSide = info->sides[0], &rightSide = info->sides[1];
|
||||
|
||||
|
||||
@ -732,7 +753,7 @@ void CClient::battleStarted(const BattleInfo * info)
|
||||
{
|
||||
boost::unique_lock<boost::recursive_mutex> un(*LOCPLINT->pim);
|
||||
auto bi = new CBattleInterface(leftSide.armyObject, rightSide.armyObject, leftSide.hero, rightSide.hero,
|
||||
Rect((screen->w - 800)/2,
|
||||
Rect((screen->w - 800)/2,
|
||||
(screen->h - 600)/2, 800, 600), att, def);
|
||||
|
||||
GH.pushInt(bi);
|
||||
@ -780,7 +801,7 @@ PlayerColor CClient::getLocalPlayer() const
|
||||
return getCurrentPlayer();
|
||||
}
|
||||
|
||||
void CClient::commenceTacticPhaseForInt(shared_ptr<CBattleGameInterface> battleInt)
|
||||
void CClient::commenceTacticPhaseForInt(std::shared_ptr<CBattleGameInterface> battleInt)
|
||||
{
|
||||
setThreadName("CClient::commenceTacticPhaseForInt");
|
||||
try
|
||||
@ -795,7 +816,7 @@ void CClient::commenceTacticPhaseForInt(shared_ptr<CBattleGameInterface> battleI
|
||||
catch(...)
|
||||
{
|
||||
handleException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CClient::invalidatePaths()
|
||||
@ -821,7 +842,7 @@ int CClient::sendRequest(const CPack *request, PlayerColor player)
|
||||
static ui32 requestCounter = 0;
|
||||
|
||||
ui32 requestID = requestCounter++;
|
||||
logNetwork->traceStream() << boost::format("Sending a request \"%s\". It'll have an ID=%d.")
|
||||
logNetwork->traceStream() << boost::format("Sending a request \"%s\". It'll have an ID=%d.")
|
||||
% typeid(*request).name() % requestID;
|
||||
|
||||
waitingRequest.pushBack(requestID);
|
||||
@ -832,7 +853,7 @@ int CClient::sendRequest(const CPack *request, PlayerColor player)
|
||||
return requestID;
|
||||
}
|
||||
|
||||
void CClient::campaignMapFinished( shared_ptr<CCampaignState> camp )
|
||||
void CClient::campaignMapFinished( std::shared_ptr<CCampaignState> camp )
|
||||
{
|
||||
endGame(false);
|
||||
|
||||
@ -855,7 +876,7 @@ void CClient::campaignMapFinished( shared_ptr<CCampaignState> camp )
|
||||
}
|
||||
}
|
||||
|
||||
void CClient::installNewPlayerInterface(shared_ptr<CGameInterface> gameInterface, boost::optional<PlayerColor> color)
|
||||
void CClient::installNewPlayerInterface(std::shared_ptr<CGameInterface> gameInterface, boost::optional<PlayerColor> color)
|
||||
{
|
||||
boost::unique_lock<boost::recursive_mutex> un(*LOCPLINT->pim);
|
||||
PlayerColor colorUsed = color.get_value_or(PlayerColor::UNFLAGGABLE);
|
||||
@ -866,7 +887,7 @@ void CClient::installNewPlayerInterface(shared_ptr<CGameInterface> gameInterface
|
||||
playerint[colorUsed] = gameInterface;
|
||||
|
||||
logGlobal->traceStream() << boost::format("\tInitializing the interface for player %s") % colorUsed;
|
||||
auto cb = make_shared<CCallback>(gs, color, this);
|
||||
auto cb = std::make_shared<CCallback>(gs, color, this);
|
||||
callbacks[colorUsed] = cb;
|
||||
battleCallbacks[colorUsed] = cb;
|
||||
gameInterface->init(cb);
|
||||
@ -874,12 +895,12 @@ void CClient::installNewPlayerInterface(shared_ptr<CGameInterface> gameInterface
|
||||
installNewBattleInterface(gameInterface, color, false);
|
||||
}
|
||||
|
||||
void CClient::installNewBattleInterface(shared_ptr<CBattleGameInterface> battleInterface, boost::optional<PlayerColor> color, bool needCallback /*= true*/)
|
||||
void CClient::installNewBattleInterface(std::shared_ptr<CBattleGameInterface> battleInterface, boost::optional<PlayerColor> color, bool needCallback /*= true*/)
|
||||
{
|
||||
boost::unique_lock<boost::recursive_mutex> un(*LOCPLINT->pim);
|
||||
PlayerColor colorUsed = color.get_value_or(PlayerColor::UNFLAGGABLE);
|
||||
|
||||
if(!color)
|
||||
if(!color)
|
||||
privilagedBattleEventReceivers.push_back(battleInterface);
|
||||
|
||||
battleints[colorUsed] = battleInterface;
|
||||
@ -887,7 +908,7 @@ void CClient::installNewBattleInterface(shared_ptr<CBattleGameInterface> battleI
|
||||
if(needCallback)
|
||||
{
|
||||
logGlobal->traceStream() << boost::format("\tInitializing the battle interface for player %s") % *color;
|
||||
auto cbc = make_shared<CBattleCallback>(gs, color, this);
|
||||
auto cbc = std::make_shared<CBattleCallback>(gs, color, this);
|
||||
battleCallbacks[colorUsed] = cbc;
|
||||
battleInterface->init(cbc);
|
||||
}
|
||||
@ -915,17 +936,25 @@ std::string CClient::aiNameForPlayer(const PlayerSettings &ps, bool battleAI)
|
||||
return goodAI;
|
||||
}
|
||||
|
||||
bool CServerHandler::DO_NOT_START_SERVER = false;
|
||||
|
||||
void CServerHandler::startServer()
|
||||
{
|
||||
if(DO_NOT_START_SERVER)
|
||||
return;
|
||||
|
||||
th.update();
|
||||
|
||||
serverThread = new boost::thread(&CServerHandler::callServer, this); //runs server executable;
|
||||
if(verbose)
|
||||
logNetwork->infoStream() << "Setting up thread calling server: " << th.getDiff();
|
||||
logNetwork->infoStream() << "Setting up thread calling server: " << th.getDiff();
|
||||
}
|
||||
|
||||
void CServerHandler::waitForServer()
|
||||
{
|
||||
if(DO_NOT_START_SERVER)
|
||||
return;
|
||||
|
||||
if(!serverThread)
|
||||
startServer();
|
||||
|
||||
@ -938,7 +967,7 @@ void CServerHandler::waitForServer()
|
||||
}
|
||||
#endif
|
||||
if(verbose)
|
||||
logNetwork->infoStream() << "Waiting for server: " << th.getDiff();
|
||||
logNetwork->infoStream() << "Waiting for server: " << th.getDiff();
|
||||
}
|
||||
|
||||
CConnection * CServerHandler::connectToServer()
|
||||
@ -951,11 +980,11 @@ CConnection * CServerHandler::connectToServer()
|
||||
#endif
|
||||
|
||||
th.update(); //put breakpoint here to attach to server before it does something stupid
|
||||
|
||||
|
||||
CConnection *ret = justConnectToServer(settings["server"]["server"].String(), port);
|
||||
|
||||
if(verbose)
|
||||
logNetwork->infoStream()<<"\tConnecting to the server: "<<th.getDiff();
|
||||
logNetwork->infoStream()<<"\tConnecting to the server: "<<th.getDiff();
|
||||
|
||||
return ret;
|
||||
}
|
||||
@ -964,7 +993,10 @@ CServerHandler::CServerHandler(bool runServer /*= false*/)
|
||||
{
|
||||
serverThread = nullptr;
|
||||
shared = nullptr;
|
||||
port = boost::lexical_cast<std::string>(settings["server"]["port"].Float());
|
||||
if(settings["testing"]["enabled"].Bool())
|
||||
port = settings["testing"]["port"].String();
|
||||
else
|
||||
port = boost::lexical_cast<std::string>(settings["server"]["port"].Float());
|
||||
verbose = true;
|
||||
|
||||
#ifndef VCMI_ANDROID
|
||||
@ -972,13 +1004,13 @@ CServerHandler::CServerHandler(bool runServer /*= false*/)
|
||||
try
|
||||
{
|
||||
shared = new SharedMem();
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
logNetwork->error("Cannot open interprocess memory.");
|
||||
handleException();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
logNetwork->error("Cannot open interprocess memory.");
|
||||
handleException();
|
||||
throw;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -995,30 +1027,38 @@ void CServerHandler::callServer()
|
||||
const std::string comm = VCMIDirs::get().serverPath().string() + " --port=" + port + " > \"" + logName + '\"';
|
||||
int result = std::system(comm.c_str());
|
||||
if (result == 0)
|
||||
logNetwork->infoStream() << "Server closed correctly";
|
||||
logNetwork->infoStream() << "Server closed correctly";
|
||||
else
|
||||
{
|
||||
logNetwork->errorStream() << "Error: server failed to close correctly or crashed!";
|
||||
logNetwork->errorStream() << "Check " << logName << " for more info";
|
||||
logNetwork->errorStream() << "Error: server failed to close correctly or crashed!";
|
||||
logNetwork->errorStream() << "Check " << logName << " for more info";
|
||||
exit(1);// exit in case of error. Othervice without working server VCMI will hang
|
||||
}
|
||||
}
|
||||
|
||||
CConnection * CServerHandler::justConnectToServer(const std::string &host, const std::string &port)
|
||||
{
|
||||
std::string realPort;
|
||||
if(settings["testing"]["enabled"].Bool())
|
||||
realPort = settings["testing"]["port"].String();
|
||||
else if(port.size())
|
||||
realPort = port;
|
||||
else
|
||||
realPort = boost::lexical_cast<std::string>(settings["server"]["port"].Float());
|
||||
|
||||
CConnection *ret = nullptr;
|
||||
while(!ret)
|
||||
{
|
||||
try
|
||||
{
|
||||
logNetwork->infoStream() << "Establishing connection...";
|
||||
ret = new CConnection( host.size() ? host : settings["server"]["server"].String(),
|
||||
port.size() ? port : boost::lexical_cast<std::string>(settings["server"]["port"].Float()),
|
||||
logNetwork->infoStream() << "Establishing connection...";
|
||||
ret = new CConnection( host.size() ? host : settings["server"]["server"].String(),
|
||||
realPort,
|
||||
NAME);
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
logNetwork->errorStream() << "\nCannot establish connection! Retrying within 2 seconds";
|
||||
logNetwork->errorStream() << "\nCannot establish connection! Retrying within 2 seconds";
|
||||
SDL_Delay(2000);
|
||||
}
|
||||
}
|
||||
|
@ -16,7 +16,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
class CPack;
|
||||
struct CPack;
|
||||
class CCampaignState;
|
||||
class CBattleCallback;
|
||||
class IGameEventsReceiver;
|
||||
@ -32,8 +32,8 @@ struct SharedMem;
|
||||
class CClient;
|
||||
class CScriptingModule;
|
||||
struct CPathsInfo;
|
||||
class CISer;
|
||||
class COSer;
|
||||
class BinaryDeserializer;
|
||||
class BinarySerializer;
|
||||
namespace boost { class thread; }
|
||||
|
||||
/// structure to handle running server and connecting to it
|
||||
@ -42,6 +42,8 @@ class CServerHandler
|
||||
private:
|
||||
void callServer(); //calls server via system(), should be called as thread
|
||||
public:
|
||||
static bool DO_NOT_START_SERVER;
|
||||
|
||||
CStopWatch th;
|
||||
boost::thread *serverThread; //thread that called system to run server
|
||||
SharedMem *shared; //interprocess memory (for waiting for server)
|
||||
@ -57,7 +59,7 @@ public:
|
||||
static CConnection * justConnectToServer(const std::string &host = "", const std::string &port = ""); //connects to given host without taking any other actions (like setting up server)
|
||||
|
||||
CServerHandler(bool runServer = false);
|
||||
~CServerHandler();
|
||||
virtual ~CServerHandler();
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
@ -70,7 +72,6 @@ class ThreadSafeVector
|
||||
boost::condition_variable cond;
|
||||
|
||||
public:
|
||||
|
||||
void pushBack(const T &item)
|
||||
{
|
||||
TLock lock(mx);
|
||||
@ -115,17 +116,17 @@ public:
|
||||
/// Class which handles client - server logic
|
||||
class CClient : public IGameCallback
|
||||
{
|
||||
unique_ptr<CPathsInfo> pathInfo;
|
||||
std::unique_ptr<CPathsInfo> pathInfo;
|
||||
public:
|
||||
std::map<PlayerColor,shared_ptr<CCallback> > callbacks; //callbacks given to player interfaces
|
||||
std::map<PlayerColor,shared_ptr<CBattleCallback> > battleCallbacks; //callbacks given to player interfaces
|
||||
std::vector<shared_ptr<IGameEventsReceiver>> privilagedGameEventReceivers; //scripting modules, spectator interfaces
|
||||
std::vector<shared_ptr<IBattleEventsReceiver>> privilagedBattleEventReceivers; //scripting modules, spectator interfaces
|
||||
std::map<PlayerColor, shared_ptr<CGameInterface>> playerint;
|
||||
std::map<PlayerColor, shared_ptr<CBattleGameInterface>> battleints;
|
||||
std::map<PlayerColor,std::shared_ptr<CCallback> > callbacks; //callbacks given to player interfaces
|
||||
std::map<PlayerColor,std::shared_ptr<CBattleCallback> > battleCallbacks; //callbacks given to player interfaces
|
||||
std::vector<std::shared_ptr<IGameEventsReceiver>> privilagedGameEventReceivers; //scripting modules, spectator interfaces
|
||||
std::vector<std::shared_ptr<IBattleEventsReceiver>> privilagedBattleEventReceivers; //scripting modules, spectator interfaces
|
||||
std::map<PlayerColor, std::shared_ptr<CGameInterface>> playerint;
|
||||
std::map<PlayerColor, std::shared_ptr<CBattleGameInterface>> battleints;
|
||||
|
||||
std::map<PlayerColor,std::vector<shared_ptr<IGameEventsReceiver>>> additionalPlayerInts;
|
||||
std::map<PlayerColor,std::vector<shared_ptr<IBattleEventsReceiver>>> additionalBattleInts;
|
||||
std::map<PlayerColor,std::vector<std::shared_ptr<IGameEventsReceiver>>> additionalPlayerInts;
|
||||
std::map<PlayerColor,std::vector<std::shared_ptr<IBattleEventsReceiver>>> additionalBattleInts;
|
||||
|
||||
bool hotSeat;
|
||||
CConnection *serv;
|
||||
@ -146,8 +147,8 @@ public:
|
||||
void newGame(CConnection *con, StartInfo *si); //con - connection to server
|
||||
|
||||
void loadNeutralBattleAI();
|
||||
void installNewPlayerInterface(shared_ptr<CGameInterface> gameInterface, boost::optional<PlayerColor> color);
|
||||
void installNewBattleInterface(shared_ptr<CBattleGameInterface> battleInterface, boost::optional<PlayerColor> color, bool needCallback = true);
|
||||
void installNewPlayerInterface(std::shared_ptr<CGameInterface> gameInterface, boost::optional<PlayerColor> color);
|
||||
void installNewBattleInterface(std::shared_ptr<CBattleGameInterface> battleInterface, boost::optional<PlayerColor> color, bool needCallback = true);
|
||||
std::string aiNameForPlayer(const PlayerSettings &ps, bool battleAI); //empty means no AI -> human
|
||||
|
||||
void endGame(bool closeConnection = true);
|
||||
@ -155,9 +156,9 @@ public:
|
||||
void save(const std::string & fname);
|
||||
void loadGame(const std::string & fname, const bool server = true, const std::vector<int>& humanplayerindices = std::vector<int>(), const int loadnumplayers = 1, int player_ = -1, const std::string & ipaddr = "", const std::string & port = "");
|
||||
void run();
|
||||
void campaignMapFinished( shared_ptr<CCampaignState> camp );
|
||||
void finishCampaign( shared_ptr<CCampaignState> camp );
|
||||
void proposeNextMission(shared_ptr<CCampaignState> camp);
|
||||
void campaignMapFinished( std::shared_ptr<CCampaignState> camp );
|
||||
void finishCampaign( std::shared_ptr<CCampaignState> camp );
|
||||
void proposeNextMission(std::shared_ptr<CCampaignState> camp);
|
||||
|
||||
void invalidatePaths();
|
||||
const CPathsInfo * getPathsInfo(const CGHeroInstance *h);
|
||||
@ -175,9 +176,9 @@ public:
|
||||
void setBlockVis(ObjectInstanceID objid, bool bv) override {};
|
||||
void setOwner(const CGObjectInstance * obj, PlayerColor owner) override {};
|
||||
void changePrimSkill(const CGHeroInstance * hero, PrimarySkill::PrimarySkill which, si64 val, bool abs=false) override {};
|
||||
void changeSecSkill(const CGHeroInstance * hero, SecondarySkill which, int val, bool abs=false) override {};
|
||||
void changeSecSkill(const CGHeroInstance * hero, SecondarySkill which, int val, bool abs=false) override {};
|
||||
|
||||
void showBlockingDialog(BlockingDialog *iw) override {};
|
||||
void showBlockingDialog(BlockingDialog *iw) override {};
|
||||
void showGarrisonDialog(ObjectInstanceID upobj, ObjectInstanceID hid, bool removableUnits) override {};
|
||||
void showTeleportDialog(TeleportDialog *iw) override {};
|
||||
void showThievesGuildWindow(PlayerColor player, ObjectInstanceID requestingObjId) override {};
|
||||
@ -186,20 +187,20 @@ public:
|
||||
|
||||
void giveCreatures(const CArmedInstance * objid, const CGHeroInstance * h, const CCreatureSet &creatures, bool remove) override {};
|
||||
void takeCreatures(ObjectInstanceID objid, const std::vector<CStackBasicDescriptor> &creatures) override {};
|
||||
bool changeStackType(const StackLocation &sl, CCreature *c) override {return false;};
|
||||
bool changeStackType(const StackLocation &sl, const CCreature *c) override {return false;};
|
||||
bool changeStackCount(const StackLocation &sl, TQuantity count, bool absoluteValue = false) override {return false;};
|
||||
bool insertNewStack(const StackLocation &sl, const CCreature *c, TQuantity count) override {return false;};
|
||||
bool eraseStack(const StackLocation &sl, bool forceRemoval = false){return false;};
|
||||
bool eraseStack(const StackLocation &sl, bool forceRemoval = false) override{return false;};
|
||||
bool swapStacks(const StackLocation &sl1, const StackLocation &sl2) override {return false;}
|
||||
bool addToSlot(const StackLocation &sl, const CCreature *c, TQuantity count) override {return false;}
|
||||
void tryJoiningArmy(const CArmedInstance *src, const CArmedInstance *dst, bool removeObjWhenFinished, bool allowMerging) override {}
|
||||
bool moveStack(const StackLocation &src, const StackLocation &dst, TQuantity count = -1) override {return false;}
|
||||
|
||||
|
||||
void removeAfterVisit(const CGObjectInstance *object) override {};
|
||||
|
||||
void giveHeroNewArtifact(const CGHeroInstance *h, const CArtifact *artType, ArtifactPosition pos) override {};
|
||||
void giveHeroArtifact(const CGHeroInstance *h, const CArtifactInstance *a, ArtifactPosition pos) override {};
|
||||
void putArtifact(const ArtifactLocation &al, const CArtifactInstance *a) override {};
|
||||
void putArtifact(const ArtifactLocation &al, const CArtifactInstance *a) override {};
|
||||
void removeArtifact(const ArtifactLocation &al) override {};
|
||||
bool moveArtifact(const ArtifactLocation &al1, const ArtifactLocation &al2) override {return false;};
|
||||
void synchronizeArtifactHandlerLists() override {};
|
||||
@ -207,8 +208,6 @@ public:
|
||||
void showCompInfo(ShowInInfobox * comp) override {};
|
||||
void heroVisitCastle(const CGTownInstance * obj, const CGHeroInstance * hero) override {};
|
||||
void stopHeroVisitCastle(const CGTownInstance * obj, const CGHeroInstance * hero) override {};
|
||||
//void giveHeroArtifact(int artid, int hid, int position){};
|
||||
//void giveNewArtifact(int hid, int position){};
|
||||
void startBattlePrimary(const CArmedInstance *army1, const CArmedInstance *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, bool creatureBank = false, const CGTownInstance *town = nullptr) override {}; //use hero=nullptr for no hero
|
||||
void startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, int3 tile, bool creatureBank = false) override {}; //if any of armies is hero, hero will be used
|
||||
void startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, bool creatureBank = false) override {}; //if any of armies is hero, hero will be used, visitable tile of second obj is place of battle
|
||||
@ -233,16 +232,16 @@ public:
|
||||
|
||||
void handlePack( CPack * pack ); //applies the given pack and deletes it
|
||||
void battleStarted(const BattleInfo * info);
|
||||
void commenceTacticPhaseForInt(shared_ptr<CBattleGameInterface> battleInt); //will be called as separate thread
|
||||
void commenceTacticPhaseForInt(std::shared_ptr<CBattleGameInterface> battleInt); //will be called as separate thread
|
||||
|
||||
void commitPackage(CPackForClient *pack) override;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void serialize(COSer &h, const int version);
|
||||
void serialize(CISer &h, const int version);
|
||||
|
||||
void serialize(COSer &h, const int version, const std::set<PlayerColor>& playerIDs);
|
||||
void serialize(CISer &h, const int version, const std::set<PlayerColor>& playerIDs);
|
||||
void serialize(BinarySerializer & h, const int version);
|
||||
void serialize(BinaryDeserializer & h, const int version);
|
||||
|
||||
void serialize(BinarySerializer & h, const int version, const std::set<PlayerColor>& playerIDs);
|
||||
void serialize(BinaryDeserializer & h, const int version, const std::set<PlayerColor>& playerIDs);
|
||||
void battleFinished();
|
||||
};
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include "../lib/filesystem/CBinaryReader.h"
|
||||
#include "CDefHandler.h"
|
||||
#include "gui/SDL_Extensions.h"
|
||||
#include "gui/CAnimation.h"
|
||||
#include <SDL_ttf.h>
|
||||
#include "../lib/CThreadHelper.h"
|
||||
#include "CGameInfo.h"
|
||||
@ -19,9 +20,9 @@
|
||||
#include "../lib/CGameState.h"
|
||||
#include "../lib/JsonNode.h"
|
||||
#include "../lib/vcmi_endian.h"
|
||||
#include "../lib/GameConstants.h"
|
||||
#include "../lib/CStopWatch.h"
|
||||
#include "../lib/mapObjects/CObjectClassesHandler.h"
|
||||
#include "../lib/mapObjects/CObjectHandler.h"
|
||||
|
||||
using namespace CSDL_Ext;
|
||||
#ifdef min
|
||||
@ -58,7 +59,7 @@ void Graphics::loadPaletteAndColors()
|
||||
col.r = pals[startPoint++];
|
||||
col.g = pals[startPoint++];
|
||||
col.b = pals[startPoint++];
|
||||
CSDL_Ext::colorSetAlpha(col,SDL_ALPHA_OPAQUE);
|
||||
col.a = SDL_ALPHA_OPAQUE;
|
||||
startPoint++;
|
||||
playerColorPalette[i] = col;
|
||||
}
|
||||
@ -74,32 +75,35 @@ void Graphics::loadPaletteAndColors()
|
||||
neutralColorPalette[i].g = reader.readUInt8();
|
||||
neutralColorPalette[i].b = reader.readUInt8();
|
||||
reader.readUInt8(); // this is "flags" entry, not alpha
|
||||
CSDL_Ext::colorSetAlpha(neutralColorPalette[i], SDL_ALPHA_OPAQUE);
|
||||
neutralColorPalette[i].a = SDL_ALPHA_OPAQUE;
|
||||
}
|
||||
//colors initialization
|
||||
SDL_Color colors[] = {
|
||||
{0xff,0, 0, SDL_ALPHA_OPAQUE},
|
||||
SDL_Color colors[] = {
|
||||
{0xff,0, 0, SDL_ALPHA_OPAQUE},
|
||||
{0x31,0x52,0xff,SDL_ALPHA_OPAQUE},
|
||||
{0x9c,0x73,0x52,SDL_ALPHA_OPAQUE},
|
||||
{0x42,0x94,0x29,SDL_ALPHA_OPAQUE},
|
||||
|
||||
|
||||
{0xff,0x84,0, SDL_ALPHA_OPAQUE},
|
||||
{0x8c,0x29,0xa5,SDL_ALPHA_OPAQUE},
|
||||
{0x09,0x9c,0xa5,SDL_ALPHA_OPAQUE},
|
||||
{0xc6,0x7b,0x8c,SDL_ALPHA_OPAQUE}};
|
||||
|
||||
{0xc6,0x7b,0x8c,SDL_ALPHA_OPAQUE}};
|
||||
|
||||
for(int i=0;i<8;i++)
|
||||
{
|
||||
playerColors[i] = colors[i];
|
||||
}
|
||||
neutralColor->r = 0x84; neutralColor->g = 0x84; neutralColor->b = 0x84; //gray
|
||||
CSDL_Ext::colorSetAlpha(*neutralColor,SDL_ALPHA_OPAQUE);
|
||||
//gray
|
||||
neutralColor->r = 0x84;
|
||||
neutralColor->g = 0x84;
|
||||
neutralColor->b = 0x84;
|
||||
neutralColor->a = SDL_ALPHA_OPAQUE;
|
||||
}
|
||||
|
||||
void Graphics::initializeBattleGraphics()
|
||||
{
|
||||
const JsonNode config(ResourceID("config/battles_graphics.json"));
|
||||
|
||||
|
||||
// Reserve enough space for the terrains
|
||||
int idx = config["backgrounds"].Vector().size();
|
||||
battleBacks.resize(idx+1); // 1 to idx, 0 is unused
|
||||
@ -120,11 +124,20 @@ void Graphics::initializeBattleGraphics()
|
||||
}
|
||||
|
||||
battleACToDef[ACid] = toAdd;
|
||||
}
|
||||
}
|
||||
}
|
||||
Graphics::Graphics()
|
||||
{
|
||||
#if 0
|
||||
|
||||
#define GET_DATA(TYPE,DESTINATION,FUNCTION_TO_GET) \
|
||||
(std::bind(&setData<TYPE>,&DESTINATION,FUNCTION_TO_GET))
|
||||
|
||||
#define GET_DEF_ESS(DESTINATION, DEF_NAME) \
|
||||
(GET_DATA \
|
||||
(CDefEssential*,DESTINATION,\
|
||||
std::function<CDefEssential*()>(std::bind(CDefHandler::giveDefEss,DEF_NAME))))
|
||||
|
||||
std::vector<Task> tasks; //preparing list of graphics to load
|
||||
tasks += std::bind(&Graphics::loadFonts,this);
|
||||
tasks += std::bind(&Graphics::loadPaletteAndColors,this);
|
||||
@ -132,8 +145,6 @@ Graphics::Graphics()
|
||||
tasks += std::bind(&Graphics::initializeBattleGraphics,this);
|
||||
tasks += std::bind(&Graphics::loadErmuToPicture,this);
|
||||
tasks += std::bind(&Graphics::initializeImageLists,this);
|
||||
tasks += GET_DEF_ESS(resources32,"RESOURCE.DEF");
|
||||
tasks += GET_DEF_ESS(heroMoveArrows,"ADAG.DEF");
|
||||
|
||||
CThreadHelper th(&tasks,std::max((ui32)1,boost::thread::hardware_concurrency()));
|
||||
th.run();
|
||||
@ -144,20 +155,23 @@ Graphics::Graphics()
|
||||
initializeBattleGraphics();
|
||||
loadErmuToPicture();
|
||||
initializeImageLists();
|
||||
resources32 = CDefHandler::giveDefEss("RESOURCE.DEF");
|
||||
heroMoveArrows = CDefHandler::giveDefEss("ADAG.DEF");
|
||||
#endif
|
||||
|
||||
for(auto & elem : heroMoveArrows->ourImages)
|
||||
{
|
||||
CSDL_Ext::alphaTransform(elem.bitmap);
|
||||
}
|
||||
//(!) do not load any CAnimation here
|
||||
}
|
||||
|
||||
void Graphics::load()
|
||||
{
|
||||
heroMoveArrows = std::make_shared<CAnimation>("ADAG");
|
||||
heroMoveArrows->preload();
|
||||
|
||||
loadHeroAnims();
|
||||
}
|
||||
|
||||
void Graphics::loadHeroAnims()
|
||||
{
|
||||
//first - group number to be rotated1, second - group number after rotation1
|
||||
std::vector<std::pair<int,int> > rotations =
|
||||
std::vector<std::pair<int,int> > rotations =
|
||||
{
|
||||
{6,10}, {7,11}, {8,12}, {1,13},
|
||||
{2,14}, {3,15}
|
||||
@ -219,11 +233,11 @@ void Graphics::loadHeroFlagsDetail(std::pair<std::vector<CDefEssential *> Graphi
|
||||
for(int i=0;i<8;i++)
|
||||
(this->*pr.first).push_back(CDefHandler::giveDefEss(pr.second[i]));
|
||||
//first - group number to be rotated1, second - group number after rotation1
|
||||
std::vector<std::pair<int,int> > rotations =
|
||||
std::vector<std::pair<int,int> > rotations =
|
||||
{
|
||||
{6,10}, {7,11}, {8,12}
|
||||
};
|
||||
|
||||
|
||||
for(int q=0; q<8; ++q)
|
||||
{
|
||||
std::vector<Cimage> &curImgs = (this->*pr.first)[q]->ourImages;
|
||||
@ -266,9 +280,7 @@ void Graphics::loadHeroFlagsDetail(std::pair<std::vector<CDefEssential *> Graphi
|
||||
for(auto & curImg : curImgs)
|
||||
{
|
||||
CSDL_Ext::setDefaultColorKey(curImg.bitmap);
|
||||
#ifndef VCMI_SDL1
|
||||
SDL_SetSurfaceBlendMode(curImg.bitmap,SDL_BLENDMODE_NONE);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -279,15 +291,15 @@ void Graphics::loadHeroFlags()
|
||||
std::pair<std::vector<CDefEssential *> Graphics::*, std::vector<const char *> > pr[4] =
|
||||
{
|
||||
{
|
||||
&Graphics::flags1,
|
||||
&Graphics::flags1,
|
||||
{"ABF01L.DEF","ABF01G.DEF","ABF01R.DEF","ABF01D.DEF","ABF01B.DEF",
|
||||
"ABF01P.DEF","ABF01W.DEF","ABF01K.DEF"}
|
||||
"ABF01P.DEF","ABF01W.DEF","ABF01K.DEF"}
|
||||
},
|
||||
{
|
||||
&Graphics::flags2,
|
||||
{"ABF02L.DEF","ABF02G.DEF","ABF02R.DEF","ABF02D.DEF","ABF02B.DEF",
|
||||
"ABF02P.DEF","ABF02W.DEF","ABF02K.DEF"}
|
||||
|
||||
|
||||
},
|
||||
{
|
||||
&Graphics::flags3,
|
||||
@ -298,7 +310,7 @@ void Graphics::loadHeroFlags()
|
||||
&Graphics::flags4,
|
||||
{"AF00.DEF","AF01.DEF","AF02.DEF","AF03.DEF","AF04.DEF",
|
||||
"AF05.DEF","AF06.DEF","AF07.DEF"}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#if 0
|
||||
@ -314,7 +326,7 @@ void Graphics::loadHeroFlags()
|
||||
loadHeroFlagsDetail(p,true);
|
||||
}
|
||||
#endif
|
||||
logGlobal->infoStream() << "Loading and transforming heroes' flags: "<<th.getDiff();
|
||||
logGlobal->infoStream() << "Loading and transforming heroes' flags: "<<th.getDiff();
|
||||
}
|
||||
|
||||
void Graphics::blueToPlayersAdv(SDL_Surface * sur, PlayerColor player)
|
||||
@ -332,7 +344,7 @@ void Graphics::blueToPlayersAdv(SDL_Surface * sur, PlayerColor player)
|
||||
}
|
||||
else
|
||||
{
|
||||
logGlobal->errorStream() << "Wrong player id in blueToPlayersAdv (" << player << ")!";
|
||||
logGlobal->errorStream() << "Wrong player id in blueToPlayersAdv (" << player << ")!";
|
||||
return;
|
||||
}
|
||||
SDL_SetColors(sur, palette, 224, 32);
|
||||
@ -372,11 +384,21 @@ void Graphics::loadFonts()
|
||||
|
||||
CDefEssential * Graphics::getDef( const CGObjectInstance * obj )
|
||||
{
|
||||
if (obj->appearance.animationFile.empty())
|
||||
{
|
||||
logGlobal->warnStream() << boost::format("Def name for obj %d (%d,%d) is empty!") % obj->id % obj->ID % obj->subID;
|
||||
return nullptr;
|
||||
}
|
||||
return advmapobjGraphics[obj->appearance.animationFile];
|
||||
}
|
||||
|
||||
CDefEssential * Graphics::getDef( const ObjectTemplate & info )
|
||||
{
|
||||
if (info.animationFile.empty())
|
||||
{
|
||||
logGlobal->warnStream() << boost::format("Def name for obj (%d,%d) is empty!") % info.id % info.subid;
|
||||
return nullptr;
|
||||
}
|
||||
return advmapobjGraphics[info.animationFile];
|
||||
}
|
||||
|
||||
@ -448,12 +470,12 @@ void Graphics::initializeImageLists()
|
||||
addImageListEntry(info.icons[1][1] + 2, "ITPA", info.iconSmall[1][1]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for(const CSpell * spell : CGI->spellh->objects)
|
||||
{
|
||||
addImageListEntry(spell->id, "SPELLS", spell->iconBook);
|
||||
addImageListEntry(spell->id+1, "SPELLINT", spell->iconEffect);
|
||||
addImageListEntry(spell->id, "SPELLBON", spell->iconScenarioBonus);
|
||||
addImageListEntry(spell->id, "SPELLSCR", spell->iconScroll);
|
||||
addImageListEntry(spell->id, "SPELLSCR", spell->iconScroll);
|
||||
}
|
||||
}
|
||||
|
@ -38,20 +38,30 @@ class Graphics
|
||||
{
|
||||
void addImageListEntry(size_t index, std::string listName, std::string imageName);
|
||||
|
||||
void initializeBattleGraphics();
|
||||
void loadPaletteAndColors();
|
||||
void loadHeroFlags();
|
||||
void loadHeroFlagsDetail(std::pair<std::vector<CDefEssential *> Graphics::*, std::vector<const char *> > &pr, bool mode);
|
||||
void loadHeroAnims();
|
||||
CDefEssential * loadHeroAnim(const std::string &name, const std::vector<std::pair<int,int> > &rotations);
|
||||
void loadErmuToPicture();
|
||||
|
||||
void loadFonts();
|
||||
void initializeImageLists();
|
||||
|
||||
public:
|
||||
//Fonts
|
||||
static const int FONTS_NUMBER = 9;
|
||||
IFont * fonts[FONTS_NUMBER];
|
||||
|
||||
|
||||
//various graphics
|
||||
SDL_Color * playerColors; //array [8]
|
||||
SDL_Color * neutralColor;
|
||||
SDL_Color * playerColorPalette; //palette to make interface colors good - array of size [256]
|
||||
SDL_Color * neutralColorPalette;
|
||||
SDL_Color * neutralColorPalette;
|
||||
|
||||
std::vector<CDefEssential *> flags1, flags2, flags3, flags4; //flags blitted on heroes when ,
|
||||
CDefEssential * resources32; //resources 32x32
|
||||
CDefEssential * heroMoveArrows;
|
||||
std::shared_ptr<CAnimation> heroMoveArrows;
|
||||
std::map<std::string, CDefEssential *> heroAnims; // [hero class def name] //added group 10: up - left, 11 - left and 12 - left down // 13 - up-left standing; 14 - left standing; 15 - left down standing
|
||||
std::vector<CDefEssential *> boatAnims; // [boat type: 0 - 3] //added group 10: up - left, 11 - left and 12 - left down // 13 - up-left standing; 14 - left standing; 15 - left down standing
|
||||
CDefHandler * FoWfullHide; //for Fog of War
|
||||
@ -68,18 +78,11 @@ public:
|
||||
std::vector< std::vector< std::string > > battleBacks; //battleBacks[terType] - vector of possible names for certain terrain type
|
||||
std::map< int, std::vector < std::string > > battleACToDef; //maps AC format to vector of appropriate def names
|
||||
//functions
|
||||
Graphics();
|
||||
void initializeBattleGraphics();
|
||||
void loadPaletteAndColors();
|
||||
void loadHeroFlags();
|
||||
void loadHeroFlagsDetail(std::pair<std::vector<CDefEssential *> Graphics::*, std::vector<const char *> > &pr, bool mode);
|
||||
void loadHeroAnims();
|
||||
CDefEssential * loadHeroAnim(const std::string &name, const std::vector<std::pair<int,int> > &rotations);
|
||||
void loadErmuToPicture();
|
||||
void blueToPlayersAdv(SDL_Surface * sur, PlayerColor player); //replaces blue interface colour with a color of player
|
||||
Graphics();
|
||||
|
||||
void loadFonts();
|
||||
void initializeImageLists();
|
||||
void load();
|
||||
|
||||
void blueToPlayersAdv(SDL_Surface * sur, PlayerColor player); //replaces blue interface colour with a color of player
|
||||
};
|
||||
|
||||
extern Graphics * graphics;
|
||||
|
@ -2,12 +2,13 @@
|
||||
#include "../lib/NetPacks.h"
|
||||
|
||||
#include "../lib/filesystem/Filesystem.h"
|
||||
#include "../lib/filesystem/CFileInfo.h"
|
||||
#include "../lib/filesystem/FileInfo.h"
|
||||
#include "../CCallback.h"
|
||||
#include "Client.h"
|
||||
#include "CPlayerInterface.h"
|
||||
#include "CGameInfo.h"
|
||||
#include "../lib/Connection.h"
|
||||
#include "../lib/serializer/Connection.h"
|
||||
#include "../lib/serializer/BinarySerializer.h"
|
||||
#include "../lib/CGeneralTextHandler.h"
|
||||
#include "../lib/CHeroHandler.h"
|
||||
#include "../lib/VCMI_Lib.h"
|
||||
@ -25,6 +26,7 @@
|
||||
#include "../lib/CGameState.h"
|
||||
#include "../lib/BattleState.h"
|
||||
#include "../lib/GameConstants.h"
|
||||
#include "../lib/CPlayerState.h"
|
||||
#include "gui/CGuiHandler.h"
|
||||
#include "widgets/MiscWidgets.h"
|
||||
#include "widgets/AdventureMapClasses.h"
|
||||
@ -104,39 +106,39 @@
|
||||
*
|
||||
*/
|
||||
|
||||
void SetResources::applyCl( CClient *cl )
|
||||
void SetResources::applyCl(CClient *cl)
|
||||
{
|
||||
INTERFACE_CALL_IF_PRESENT(player,receivedResource,-1,-1);
|
||||
}
|
||||
|
||||
void SetResource::applyCl( CClient *cl )
|
||||
void SetResource::applyCl(CClient *cl)
|
||||
{
|
||||
INTERFACE_CALL_IF_PRESENT(player,receivedResource,resid,val);
|
||||
}
|
||||
|
||||
void SetPrimSkill::applyCl( CClient *cl )
|
||||
void SetPrimSkill::applyCl(CClient *cl)
|
||||
{
|
||||
const CGHeroInstance *h = cl->getHero(id);
|
||||
if(!h)
|
||||
{
|
||||
logNetwork->errorStream() << "Cannot find hero with ID " << id.getNum();
|
||||
logNetwork->errorStream() << "Cannot find hero with ID " << id.getNum();
|
||||
return;
|
||||
}
|
||||
INTERFACE_CALL_IF_PRESENT(h->tempOwner,heroPrimarySkillChanged,h,which,val);
|
||||
}
|
||||
|
||||
void SetSecSkill::applyCl( CClient *cl )
|
||||
void SetSecSkill::applyCl(CClient *cl)
|
||||
{
|
||||
const CGHeroInstance *h = cl->getHero(id);
|
||||
if(!h)
|
||||
{
|
||||
logNetwork->errorStream() << "Cannot find hero with ID " << id;
|
||||
logNetwork->errorStream() << "Cannot find hero with ID " << id;
|
||||
return;
|
||||
}
|
||||
INTERFACE_CALL_IF_PRESENT(h->tempOwner,heroSecondarySkillChanged,h,which,val);
|
||||
}
|
||||
|
||||
void HeroVisitCastle::applyCl( CClient *cl )
|
||||
void HeroVisitCastle::applyCl(CClient *cl)
|
||||
{
|
||||
const CGHeroInstance *h = cl->getHero(hid);
|
||||
|
||||
@ -146,25 +148,25 @@ void HeroVisitCastle::applyCl( CClient *cl )
|
||||
}
|
||||
}
|
||||
|
||||
void ChangeSpells::applyCl( CClient *cl )
|
||||
void ChangeSpells::applyCl(CClient *cl)
|
||||
{
|
||||
//TODO: inform interface?
|
||||
}
|
||||
|
||||
void SetMana::applyCl( CClient *cl )
|
||||
void SetMana::applyCl(CClient *cl)
|
||||
{
|
||||
const CGHeroInstance *h = cl->getHero(hid);
|
||||
INTERFACE_CALL_IF_PRESENT(h->tempOwner, heroManaPointsChanged, h);
|
||||
}
|
||||
|
||||
void SetMovePoints::applyCl( CClient *cl )
|
||||
void SetMovePoints::applyCl(CClient *cl)
|
||||
{
|
||||
const CGHeroInstance *h = cl->getHero(hid);
|
||||
cl->invalidatePaths();
|
||||
INTERFACE_CALL_IF_PRESENT(h->tempOwner, heroMovePointsChanged, h);
|
||||
}
|
||||
|
||||
void FoWChange::applyCl( CClient *cl )
|
||||
void FoWChange::applyCl(CClient *cl)
|
||||
{
|
||||
for(auto &i : cl->playerint)
|
||||
{
|
||||
@ -183,85 +185,85 @@ void FoWChange::applyCl( CClient *cl )
|
||||
cl->invalidatePaths();
|
||||
}
|
||||
|
||||
void SetAvailableHeroes::applyCl( CClient *cl )
|
||||
void SetAvailableHeroes::applyCl(CClient *cl)
|
||||
{
|
||||
//TODO: inform interface?
|
||||
}
|
||||
|
||||
void ChangeStackCount::applyCl( CClient *cl )
|
||||
void ChangeStackCount::applyCl(CClient *cl)
|
||||
{
|
||||
INTERFACE_CALL_IF_PRESENT(sl.army->tempOwner, stackChagedCount, sl, count, absoluteValue);
|
||||
}
|
||||
|
||||
void SetStackType::applyCl( CClient *cl )
|
||||
void SetStackType::applyCl(CClient *cl)
|
||||
{
|
||||
INTERFACE_CALL_IF_PRESENT(sl.army->tempOwner, stackChangedType, sl, *type);
|
||||
}
|
||||
|
||||
void EraseStack::applyCl( CClient *cl )
|
||||
void EraseStack::applyCl(CClient *cl)
|
||||
{
|
||||
INTERFACE_CALL_IF_PRESENT(sl.army->tempOwner, stacksErased, sl);
|
||||
}
|
||||
|
||||
void SwapStacks::applyCl( CClient *cl )
|
||||
void SwapStacks::applyCl(CClient *cl)
|
||||
{
|
||||
INTERFACE_CALL_IF_PRESENT(sl1.army->tempOwner, stacksSwapped, sl1, sl2);
|
||||
if(sl1.army->tempOwner != sl2.army->tempOwner)
|
||||
INTERFACE_CALL_IF_PRESENT(sl2.army->tempOwner, stacksSwapped, sl1, sl2);
|
||||
}
|
||||
|
||||
void InsertNewStack::applyCl( CClient *cl )
|
||||
void InsertNewStack::applyCl(CClient *cl)
|
||||
{
|
||||
INTERFACE_CALL_IF_PRESENT(sl.army->tempOwner,newStackInserted,sl, *sl.getStack());
|
||||
}
|
||||
|
||||
void RebalanceStacks::applyCl( CClient *cl )
|
||||
void RebalanceStacks::applyCl(CClient *cl)
|
||||
{
|
||||
INTERFACE_CALL_IF_PRESENT(src.army->tempOwner, stacksRebalanced, src, dst, count);
|
||||
if(src.army->tempOwner != dst.army->tempOwner)
|
||||
INTERFACE_CALL_IF_PRESENT(dst.army->tempOwner,stacksRebalanced, src, dst, count);
|
||||
}
|
||||
|
||||
void PutArtifact::applyCl( CClient *cl )
|
||||
void PutArtifact::applyCl(CClient *cl)
|
||||
{
|
||||
INTERFACE_CALL_IF_PRESENT(al.owningPlayer(), artifactPut, al);
|
||||
}
|
||||
|
||||
void EraseArtifact::applyCl( CClient *cl )
|
||||
void EraseArtifact::applyCl(CClient *cl)
|
||||
{
|
||||
INTERFACE_CALL_IF_PRESENT(al.owningPlayer(), artifactRemoved, al);
|
||||
}
|
||||
|
||||
void MoveArtifact::applyCl( CClient *cl )
|
||||
void MoveArtifact::applyCl(CClient *cl)
|
||||
{
|
||||
INTERFACE_CALL_IF_PRESENT(src.owningPlayer(), artifactMoved, src, dst);
|
||||
if(src.owningPlayer() != dst.owningPlayer())
|
||||
INTERFACE_CALL_IF_PRESENT(dst.owningPlayer(), artifactMoved, src, dst);
|
||||
}
|
||||
|
||||
void AssembledArtifact::applyCl( CClient *cl )
|
||||
void AssembledArtifact::applyCl(CClient *cl)
|
||||
{
|
||||
INTERFACE_CALL_IF_PRESENT(al.owningPlayer(), artifactAssembled, al);
|
||||
}
|
||||
|
||||
void DisassembledArtifact::applyCl( CClient *cl )
|
||||
void DisassembledArtifact::applyCl(CClient *cl)
|
||||
{
|
||||
INTERFACE_CALL_IF_PRESENT(al.owningPlayer(), artifactDisassembled, al);
|
||||
}
|
||||
|
||||
void HeroVisit::applyCl( CClient *cl )
|
||||
void HeroVisit::applyCl(CClient *cl)
|
||||
{
|
||||
assert(hero);
|
||||
INTERFACE_CALL_IF_PRESENT(player, heroVisit, hero, obj, starting);
|
||||
}
|
||||
|
||||
void NewTurn::applyCl( CClient *cl )
|
||||
void NewTurn::applyCl(CClient *cl)
|
||||
{
|
||||
cl->invalidatePaths();
|
||||
}
|
||||
|
||||
|
||||
void GiveBonus::applyCl( CClient *cl )
|
||||
void GiveBonus::applyCl(CClient *cl)
|
||||
{
|
||||
cl->invalidatePaths();
|
||||
switch(who)
|
||||
@ -281,13 +283,13 @@ void GiveBonus::applyCl( CClient *cl )
|
||||
}
|
||||
}
|
||||
|
||||
void ChangeObjPos::applyFirstCl( CClient *cl )
|
||||
void ChangeObjPos::applyFirstCl(CClient *cl)
|
||||
{
|
||||
CGObjectInstance *obj = GS(cl)->getObjInstance(objid);
|
||||
if(flags & 1)
|
||||
CGI->mh->hideObject(obj);
|
||||
}
|
||||
void ChangeObjPos::applyCl( CClient *cl )
|
||||
void ChangeObjPos::applyCl(CClient *cl)
|
||||
{
|
||||
CGObjectInstance *obj = GS(cl)->getObjInstance(objid);
|
||||
if(flags & 1)
|
||||
@ -296,12 +298,12 @@ void ChangeObjPos::applyCl( CClient *cl )
|
||||
cl->invalidatePaths();
|
||||
}
|
||||
|
||||
void PlayerEndsGame::applyCl( CClient *cl )
|
||||
void PlayerEndsGame::applyCl(CClient *cl)
|
||||
{
|
||||
CALL_IN_ALL_INTERFACES(gameOver, player, victoryLossCheckResult);
|
||||
}
|
||||
|
||||
void RemoveBonus::applyCl( CClient *cl )
|
||||
void RemoveBonus::applyCl(CClient *cl)
|
||||
{
|
||||
cl->invalidatePaths();
|
||||
switch(who)
|
||||
@ -321,7 +323,7 @@ void RemoveBonus::applyCl( CClient *cl )
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateCampaignState::applyCl( CClient *cl )
|
||||
void UpdateCampaignState::applyCl(CClient *cl)
|
||||
{
|
||||
cl->stopConnection();
|
||||
cl->campaignMapFinished(camp);
|
||||
@ -332,7 +334,7 @@ void PrepareForAdvancingCampaign::applyCl(CClient *cl)
|
||||
cl->serv->prepareForSendingHeroes();
|
||||
}
|
||||
|
||||
void RemoveObject::applyFirstCl( CClient *cl )
|
||||
void RemoveObject::applyFirstCl(CClient *cl)
|
||||
{
|
||||
const CGObjectInstance *o = cl->getObj(id);
|
||||
|
||||
@ -346,12 +348,12 @@ void RemoveObject::applyFirstCl( CClient *cl )
|
||||
}
|
||||
}
|
||||
|
||||
void RemoveObject::applyCl( CClient *cl )
|
||||
void RemoveObject::applyCl(CClient *cl)
|
||||
{
|
||||
cl->invalidatePaths();
|
||||
}
|
||||
|
||||
void TryMoveHero::applyFirstCl( CClient *cl )
|
||||
void TryMoveHero::applyFirstCl(CClient *cl)
|
||||
{
|
||||
CGHeroInstance *h = GS(cl)->getHero(id);
|
||||
|
||||
@ -374,7 +376,7 @@ void TryMoveHero::applyFirstCl( CClient *cl )
|
||||
CGI->mh->printObject(h->boat);
|
||||
}
|
||||
|
||||
void TryMoveHero::applyCl( CClient *cl )
|
||||
void TryMoveHero::applyCl(CClient *cl)
|
||||
{
|
||||
const CGHeroInstance *h = cl->getHero(id);
|
||||
cl->invalidatePaths();
|
||||
@ -410,13 +412,11 @@ void TryMoveHero::applyCl( CClient *cl )
|
||||
}
|
||||
}
|
||||
|
||||
void NewStructures::applyCl( CClient *cl )
|
||||
void NewStructures::applyCl(CClient *cl)
|
||||
{
|
||||
CGTownInstance *town = GS(cl)->getTown(tid);
|
||||
for(const auto & id : bid)
|
||||
{
|
||||
town->updateAppearance();
|
||||
|
||||
if(vstd::contains(cl->playerint,town->tempOwner))
|
||||
cl->playerint[town->tempOwner]->buildChanged(town,id,1);
|
||||
}
|
||||
@ -426,14 +426,12 @@ void RazeStructures::applyCl (CClient *cl)
|
||||
CGTownInstance *town = GS(cl)->getTown(tid);
|
||||
for(const auto & id : bid)
|
||||
{
|
||||
town->updateAppearance();
|
||||
|
||||
if(vstd::contains (cl->playerint,town->tempOwner))
|
||||
cl->playerint[town->tempOwner]->buildChanged (town,id,2);
|
||||
}
|
||||
}
|
||||
|
||||
void SetAvailableCreatures::applyCl( CClient *cl )
|
||||
void SetAvailableCreatures::applyCl(CClient *cl)
|
||||
{
|
||||
const CGDwelling *dw = static_cast<const CGDwelling*>(cl->getObj(tid));
|
||||
|
||||
@ -448,28 +446,28 @@ void SetAvailableCreatures::applyCl( CClient *cl )
|
||||
INTERFACE_CALL_IF_PRESENT(p, availableCreaturesChanged, dw);
|
||||
}
|
||||
|
||||
void SetHeroesInTown::applyCl( CClient *cl )
|
||||
void SetHeroesInTown::applyCl(CClient *cl)
|
||||
{
|
||||
CGTownInstance *t = GS(cl)->getTown(tid);
|
||||
CGHeroInstance *hGarr = GS(cl)->getHero(this->garrison);
|
||||
CGHeroInstance *hVisit = GS(cl)->getHero(this->visiting);
|
||||
|
||||
std::set<PlayerColor> playersToNotify;
|
||||
//inform all players that see this object
|
||||
for(auto i = cl->playerint.cbegin(); i != cl->playerint.cend(); ++i)
|
||||
{
|
||||
if(i->first >= PlayerColor::PLAYER_LIMIT)
|
||||
continue;
|
||||
|
||||
if(vstd::contains(cl->playerint,t->tempOwner)) // our town
|
||||
playersToNotify.insert(t->tempOwner);
|
||||
|
||||
if (hGarr && vstd::contains(cl->playerint, hGarr->tempOwner))
|
||||
playersToNotify.insert(hGarr->tempOwner);
|
||||
|
||||
if (hVisit && vstd::contains(cl->playerint, hVisit->tempOwner))
|
||||
playersToNotify.insert(hVisit->tempOwner);
|
||||
|
||||
for(auto playerID : playersToNotify)
|
||||
cl->playerint[playerID]->heroInGarrisonChange(t);
|
||||
if(GS(cl)->isVisible(t, i->first) ||
|
||||
(hGarr && GS(cl)->isVisible(hGarr, i->first)) ||
|
||||
(hVisit && GS(cl)->isVisible(hVisit, i->first)))
|
||||
{
|
||||
cl->playerint[i->first]->heroInGarrisonChange(t);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// void SetHeroArtifacts::applyCl( CClient *cl )
|
||||
// void SetHeroArtifacts::applyCl(CClient *cl)
|
||||
// {
|
||||
// // CGHeroInstance *h = GS(cl)->getHero(hid);
|
||||
// // CGameInterface *player = (vstd::contains(cl->playerint,h->tempOwner) ? cl->playerint[h->tempOwner] : nullptr);
|
||||
@ -489,37 +487,43 @@ void SetHeroesInTown::applyCl( CClient *cl )
|
||||
// // }
|
||||
// }
|
||||
|
||||
void HeroRecruited::applyCl( CClient *cl )
|
||||
void HeroRecruited::applyCl(CClient *cl)
|
||||
{
|
||||
CGHeroInstance *h = GS(cl)->map->heroesOnMap.back();
|
||||
if(h->subID != hid)
|
||||
{
|
||||
logNetwork->errorStream() << "Something wrong with hero recruited!";
|
||||
logNetwork->errorStream() << "Something wrong with hero recruited!";
|
||||
}
|
||||
|
||||
CGI->mh->printObject(h);
|
||||
|
||||
if(vstd::contains(cl->playerint,h->tempOwner))
|
||||
bool needsPrinting = true;
|
||||
if(vstd::contains(cl->playerint, h->tempOwner))
|
||||
{
|
||||
cl->playerint[h->tempOwner]->heroCreated(h);
|
||||
if(const CGTownInstance *t = GS(cl)->getTown(tid))
|
||||
{
|
||||
cl->playerint[h->tempOwner]->heroInGarrisonChange(t);
|
||||
needsPrinting = false;
|
||||
}
|
||||
}
|
||||
if (needsPrinting)
|
||||
{
|
||||
CGI->mh->printObject(h);
|
||||
}
|
||||
}
|
||||
|
||||
void GiveHero::applyCl( CClient *cl )
|
||||
void GiveHero::applyCl(CClient *cl)
|
||||
{
|
||||
CGHeroInstance *h = GS(cl)->getHero(id);
|
||||
CGI->mh->printObject(h);
|
||||
cl->playerint[h->tempOwner]->heroCreated(h);
|
||||
}
|
||||
|
||||
void GiveHero::applyFirstCl( CClient *cl )
|
||||
void GiveHero::applyFirstCl(CClient *cl)
|
||||
{
|
||||
CGI->mh->hideObject(GS(cl)->getHero(id));
|
||||
}
|
||||
|
||||
void InfoWindow::applyCl( CClient *cl )
|
||||
void InfoWindow::applyCl(CClient *cl)
|
||||
{
|
||||
std::vector<Component*> comps;
|
||||
for(auto & elem : components)
|
||||
@ -532,10 +536,10 @@ void InfoWindow::applyCl( CClient *cl )
|
||||
if(vstd::contains(cl->playerint,player))
|
||||
cl->playerint.at(player)->showInfoDialog(str,comps,(soundBase::soundID)soundID);
|
||||
else
|
||||
logNetwork->warnStream() << "We received InfoWindow for not our player...";
|
||||
logNetwork->warnStream() << "We received InfoWindow for not our player...";
|
||||
}
|
||||
|
||||
void SetObjectProperty::applyCl( CClient *cl )
|
||||
void SetObjectProperty::applyCl(CClient *cl)
|
||||
{
|
||||
//inform all players that see this object
|
||||
for(auto it = cl->playerint.cbegin(); it != cl->playerint.cend(); ++it)
|
||||
@ -545,7 +549,7 @@ void SetObjectProperty::applyCl( CClient *cl )
|
||||
}
|
||||
}
|
||||
|
||||
void HeroLevelUp::applyCl( CClient *cl )
|
||||
void HeroLevelUp::applyCl(CClient *cl)
|
||||
{
|
||||
//INTERFACE_CALL_IF_PRESENT(h->tempOwner, heroGotLevel, h, primskill, skills, id);
|
||||
if(vstd::contains(cl->playerint,hero->tempOwner))
|
||||
@ -556,7 +560,7 @@ void HeroLevelUp::applyCl( CClient *cl )
|
||||
// cb->selectionMade(0, queryID);
|
||||
}
|
||||
|
||||
void CommanderLevelUp::applyCl( CClient *cl )
|
||||
void CommanderLevelUp::applyCl(CClient *cl)
|
||||
{
|
||||
const CCommanderInstance * commander = hero->commander;
|
||||
assert (commander);
|
||||
@ -567,7 +571,7 @@ void CommanderLevelUp::applyCl( CClient *cl )
|
||||
}
|
||||
}
|
||||
|
||||
void BlockingDialog::applyCl( CClient *cl )
|
||||
void BlockingDialog::applyCl(CClient *cl)
|
||||
{
|
||||
std::string str;
|
||||
text.toString(str);
|
||||
@ -575,7 +579,7 @@ void BlockingDialog::applyCl( CClient *cl )
|
||||
if(vstd::contains(cl->playerint,player))
|
||||
cl->playerint.at(player)->showBlockingDialog(str,components,queryID,(soundBase::soundID)soundID,selection(),cancel());
|
||||
else
|
||||
logNetwork->warnStream() << "We received YesNoDialog for not our player...";
|
||||
logNetwork->warnStream() << "We received YesNoDialog for not our player...";
|
||||
}
|
||||
|
||||
void GarrisonDialog::applyCl(CClient *cl)
|
||||
@ -595,12 +599,12 @@ void ExchangeDialog::applyCl(CClient *cl)
|
||||
INTERFACE_CALL_IF_PRESENT(heroes[0]->tempOwner, heroExchangeStarted, heroes[0]->id, heroes[1]->id, queryID);
|
||||
}
|
||||
|
||||
void TeleportDialog::applyCl( CClient *cl )
|
||||
void TeleportDialog::applyCl(CClient *cl)
|
||||
{
|
||||
CALL_ONLY_THAT_INTERFACE(hero->tempOwner,showTeleportDialog,channel,exits,impassable,queryID);
|
||||
}
|
||||
|
||||
void BattleStart::applyFirstCl( CClient *cl )
|
||||
void BattleStart::applyFirstCl(CClient *cl)
|
||||
{
|
||||
//Cannot use the usual macro because curB is not set yet
|
||||
CALL_ONLY_THAT_BATTLE_INTERFACE(info->sides[0].color, battleStartBefore, info->sides[0].armyObject, info->sides[1].armyObject,
|
||||
@ -611,7 +615,7 @@ void BattleStart::applyFirstCl( CClient *cl )
|
||||
info->tile, info->sides[0].hero, info->sides[1].hero);
|
||||
}
|
||||
|
||||
void BattleStart::applyCl( CClient *cl )
|
||||
void BattleStart::applyCl(CClient *cl)
|
||||
{
|
||||
cl->battleStarted(info);
|
||||
}
|
||||
@ -621,30 +625,30 @@ void BattleNextRound::applyFirstCl(CClient *cl)
|
||||
BATTLE_INTERFACE_CALL_IF_PRESENT_FOR_BOTH_SIDES(battleNewRoundFirst,round);
|
||||
}
|
||||
|
||||
void BattleNextRound::applyCl( CClient *cl )
|
||||
void BattleNextRound::applyCl(CClient *cl)
|
||||
{
|
||||
BATTLE_INTERFACE_CALL_IF_PRESENT_FOR_BOTH_SIDES(battleNewRound,round);
|
||||
}
|
||||
|
||||
void BattleSetActiveStack::applyCl( CClient *cl )
|
||||
void BattleSetActiveStack::applyCl(CClient *cl)
|
||||
{
|
||||
if(!askPlayerInterface)
|
||||
return;
|
||||
|
||||
const CStack * activated = GS(cl)->curB->battleGetStackByID(stack);
|
||||
const CStack *activated = GS(cl)->curB->battleGetStackByID(stack);
|
||||
PlayerColor playerToCall; //player that will move activated stack
|
||||
if( activated->hasBonusOfType(Bonus::HYPNOTIZED) )
|
||||
if (activated->hasBonusOfType(Bonus::HYPNOTIZED))
|
||||
{
|
||||
playerToCall = ( GS(cl)->curB->sides[0].color == activated->owner
|
||||
? GS(cl)->curB->sides[1].color
|
||||
: GS(cl)->curB->sides[0].color );
|
||||
playerToCall = (GS(cl)->curB->sides[0].color == activated->owner
|
||||
? GS(cl)->curB->sides[1].color
|
||||
: GS(cl)->curB->sides[0].color);
|
||||
}
|
||||
else
|
||||
{
|
||||
playerToCall = activated->owner;
|
||||
}
|
||||
if( vstd::contains(cl->battleints, playerToCall) )
|
||||
boost::thread( std::bind(&CClient::waitForMoveAndSend, cl, playerToCall) );
|
||||
if (vstd::contains(cl->battleints, playerToCall))
|
||||
boost::thread(std::bind(&CClient::waitForMoveAndSend, cl, playerToCall));
|
||||
}
|
||||
|
||||
void BattleTriggerEffect::applyCl(CClient * cl)
|
||||
@ -657,20 +661,25 @@ void BattleObstaclePlaced::applyCl(CClient * cl)
|
||||
BATTLE_INTERFACE_CALL_IF_PRESENT_FOR_BOTH_SIDES(battleObstaclePlaced, *obstacle);
|
||||
}
|
||||
|
||||
void BattleResult::applyFirstCl( CClient *cl )
|
||||
void BattleUpdateGateState::applyFirstCl(CClient * cl)
|
||||
{
|
||||
BATTLE_INTERFACE_CALL_IF_PRESENT_FOR_BOTH_SIDES(battleGateStateChanged, state);
|
||||
}
|
||||
|
||||
void BattleResult::applyFirstCl(CClient *cl)
|
||||
{
|
||||
BATTLE_INTERFACE_CALL_IF_PRESENT_FOR_BOTH_SIDES(battleEnd,this);
|
||||
cl->battleFinished();
|
||||
}
|
||||
|
||||
void BattleStackMoved::applyFirstCl( CClient *cl )
|
||||
void BattleStackMoved::applyFirstCl(CClient *cl)
|
||||
{
|
||||
const CStack * movedStack = GS(cl)->curB->battleGetStackByID(stack);
|
||||
BATTLE_INTERFACE_CALL_IF_PRESENT_FOR_BOTH_SIDES(battleStackMoved,movedStack,tilesToMove,distance);
|
||||
}
|
||||
|
||||
//void BattleStackAttacked::( CClient *cl )
|
||||
void BattleStackAttacked::applyFirstCl( CClient *cl )
|
||||
//void BattleStackAttacked::(CClient *cl)
|
||||
void BattleStackAttacked::applyFirstCl(CClient *cl)
|
||||
{
|
||||
std::vector<BattleStackAttacked> bsa;
|
||||
bsa.push_back(*this);
|
||||
@ -678,7 +687,7 @@ void BattleStackAttacked::applyFirstCl( CClient *cl )
|
||||
BATTLE_INTERFACE_CALL_IF_PRESENT_FOR_BOTH_SIDES(battleStacksAttacked,bsa);
|
||||
}
|
||||
|
||||
void BattleAttack::applyFirstCl( CClient *cl )
|
||||
void BattleAttack::applyFirstCl(CClient *cl)
|
||||
{
|
||||
BATTLE_INTERFACE_CALL_IF_PRESENT_FOR_BOTH_SIDES(battleAttack,this);
|
||||
for (auto & elem : bsa)
|
||||
@ -690,34 +699,34 @@ void BattleAttack::applyFirstCl( CClient *cl )
|
||||
}
|
||||
}
|
||||
|
||||
void BattleAttack::applyCl( CClient *cl )
|
||||
void BattleAttack::applyCl(CClient *cl)
|
||||
{
|
||||
BATTLE_INTERFACE_CALL_IF_PRESENT_FOR_BOTH_SIDES(battleStacksAttacked,bsa);
|
||||
}
|
||||
|
||||
void StartAction::applyFirstCl( CClient *cl )
|
||||
void StartAction::applyFirstCl(CClient *cl)
|
||||
{
|
||||
cl->curbaction = ba;
|
||||
BATTLE_INTERFACE_CALL_IF_PRESENT_FOR_BOTH_SIDES(actionStarted, ba);
|
||||
}
|
||||
|
||||
void BattleSpellCast::applyCl( CClient *cl )
|
||||
void BattleSpellCast::applyCl(CClient *cl)
|
||||
{
|
||||
BATTLE_INTERFACE_CALL_IF_PRESENT_FOR_BOTH_SIDES(battleSpellCast,this);
|
||||
}
|
||||
|
||||
void SetStackEffect::applyCl( CClient *cl )
|
||||
void SetStackEffect::applyCl(CClient *cl)
|
||||
{
|
||||
//informing about effects
|
||||
BATTLE_INTERFACE_CALL_IF_PRESENT_FOR_BOTH_SIDES(battleStacksEffectsSet,*this);
|
||||
}
|
||||
|
||||
void StacksInjured::applyCl( CClient *cl )
|
||||
void StacksInjured::applyCl(CClient *cl)
|
||||
{
|
||||
BATTLE_INTERFACE_CALL_IF_PRESENT_FOR_BOTH_SIDES(battleStacksAttacked,stacks);
|
||||
}
|
||||
|
||||
void BattleResultsApplied::applyCl( CClient *cl )
|
||||
void BattleResultsApplied::applyCl(CClient *cl)
|
||||
{
|
||||
INTERFACE_CALL_IF_PRESENT(player1, battleResultsApplied);
|
||||
INTERFACE_CALL_IF_PRESENT(player2, battleResultsApplied);
|
||||
@ -728,7 +737,7 @@ void BattleResultsApplied::applyCl( CClient *cl )
|
||||
}
|
||||
}
|
||||
|
||||
void StacksHealedOrResurrected::applyCl( CClient *cl )
|
||||
void StacksHealedOrResurrected::applyCl(CClient *cl)
|
||||
{
|
||||
std::vector<std::pair<ui32, ui32> > shiftedHealed;
|
||||
for(auto & elem : healedStacks)
|
||||
@ -738,63 +747,63 @@ void StacksHealedOrResurrected::applyCl( CClient *cl )
|
||||
BATTLE_INTERFACE_CALL_IF_PRESENT_FOR_BOTH_SIDES(battleStacksHealedRes, shiftedHealed, lifeDrain, tentHealing, drainedFrom);
|
||||
}
|
||||
|
||||
void ObstaclesRemoved::applyCl( CClient *cl )
|
||||
void ObstaclesRemoved::applyCl(CClient *cl)
|
||||
{
|
||||
//inform interfaces about removed obstacles
|
||||
BATTLE_INTERFACE_CALL_IF_PRESENT_FOR_BOTH_SIDES(battleObstaclesRemoved, obstacles);
|
||||
}
|
||||
|
||||
void CatapultAttack::applyCl( CClient *cl )
|
||||
void CatapultAttack::applyCl(CClient *cl)
|
||||
{
|
||||
//inform interfaces about catapult attack
|
||||
BATTLE_INTERFACE_CALL_IF_PRESENT_FOR_BOTH_SIDES(battleCatapultAttacked, *this);
|
||||
}
|
||||
|
||||
void BattleStacksRemoved::applyCl( CClient *cl )
|
||||
void BattleStacksRemoved::applyFirstCl(CClient * cl)
|
||||
{
|
||||
//inform interfaces about removed stacks
|
||||
BATTLE_INTERFACE_CALL_IF_PRESENT_FOR_BOTH_SIDES(battleStacksRemoved, *this);
|
||||
}
|
||||
|
||||
void BattleStackAdded::applyCl( CClient *cl )
|
||||
void BattleStackAdded::applyCl(CClient *cl)
|
||||
{
|
||||
BATTLE_INTERFACE_CALL_IF_PRESENT_FOR_BOTH_SIDES(battleNewStackAppeared, GS(cl)->curB->stacks.back());
|
||||
}
|
||||
|
||||
CGameState* CPackForClient::GS( CClient *cl )
|
||||
CGameState* CPackForClient::GS(CClient *cl)
|
||||
{
|
||||
return cl->gs;
|
||||
}
|
||||
|
||||
void EndAction::applyCl( CClient *cl )
|
||||
void EndAction::applyCl(CClient *cl)
|
||||
{
|
||||
BATTLE_INTERFACE_CALL_IF_PRESENT_FOR_BOTH_SIDES(actionFinished, *cl->curbaction);
|
||||
cl->curbaction.reset();
|
||||
}
|
||||
|
||||
void PackageApplied::applyCl( CClient *cl )
|
||||
void PackageApplied::applyCl(CClient *cl)
|
||||
{
|
||||
INTERFACE_CALL_IF_PRESENT(player, requestRealized, this);
|
||||
if(!cl->waitingRequest.tryRemovingElement(requestID))
|
||||
logNetwork->warnStream() << "Surprising server message!";
|
||||
logNetwork->warnStream() << "Surprising server message!";
|
||||
}
|
||||
|
||||
void SystemMessage::applyCl( CClient *cl )
|
||||
void SystemMessage::applyCl(CClient *cl)
|
||||
{
|
||||
std::ostringstream str;
|
||||
str << "System message: " << text;
|
||||
|
||||
logNetwork->errorStream() << str.str(); // usually used to receive error messages from server
|
||||
if(LOCPLINT)
|
||||
logNetwork->errorStream() << str.str(); // usually used to receive error messages from server
|
||||
if(LOCPLINT && !settings["session"]["hideSystemMessages"].Bool())
|
||||
LOCPLINT->cingconsole->print(str.str());
|
||||
}
|
||||
|
||||
void PlayerBlocked::applyCl( CClient *cl )
|
||||
void PlayerBlocked::applyCl(CClient *cl)
|
||||
{
|
||||
INTERFACE_CALL_IF_PRESENT(player,playerBlocked,reason, startOrEnd==BLOCKADE_STARTED);
|
||||
}
|
||||
|
||||
void YourTurn::applyCl( CClient *cl )
|
||||
void YourTurn::applyCl(CClient *cl)
|
||||
{
|
||||
CALL_IN_ALL_INTERFACES(playerStartsTurn, player);
|
||||
CALL_ONLY_THAT_INTERFACE(player,yourTurn);
|
||||
@ -802,27 +811,27 @@ void YourTurn::applyCl( CClient *cl )
|
||||
|
||||
void SaveGame::applyCl(CClient *cl)
|
||||
{
|
||||
CFileInfo info(fname);
|
||||
CResourceHandler::get("local")->createResource(info.getStem() + ".vcgm1");
|
||||
const auto stem = FileInfo::GetPathStem(fname);
|
||||
CResourceHandler::get("local")->createResource(stem.to_string() + ".vcgm1");
|
||||
|
||||
try
|
||||
{
|
||||
CSaveFile save(*CResourceHandler::get()->getResourceName(ResourceID(info.getStem(), EResType::CLIENT_SAVEGAME)));
|
||||
CSaveFile save(*CResourceHandler::get()->getResourceName(ResourceID(stem.to_string(), EResType::CLIENT_SAVEGAME)));
|
||||
cl->saveCommonState(save);
|
||||
save << *cl;
|
||||
}
|
||||
catch(std::exception &e)
|
||||
{
|
||||
logNetwork->errorStream() << "Failed to save game:" << e.what();
|
||||
logNetwork->errorStream() << "Failed to save game:" << e.what();
|
||||
}
|
||||
}
|
||||
|
||||
void PlayerMessage::applyCl(CClient *cl)
|
||||
{
|
||||
std::ostringstream str;
|
||||
str << "Player "<< player <<" sends a message: " << text;
|
||||
logNetwork->debugStream() << "Player "<< player <<" sends a message: " << text;
|
||||
|
||||
logNetwork->debugStream() << str.str();
|
||||
std::ostringstream str;
|
||||
str << cl->getPlayer(player)->nodeName() <<": " << text;
|
||||
if(LOCPLINT)
|
||||
LOCPLINT->cingconsole->print(str.str());
|
||||
}
|
||||
@ -955,6 +964,6 @@ void TradeComponents::applyCl(CClient *cl)
|
||||
case Obj::TRADING_POST_SNOW:
|
||||
break;
|
||||
default:
|
||||
logNetwork->warnStream() << "Shop type not supported!";
|
||||
logNetwork->warnStream() << "Shop type not supported!";
|
||||
}
|
||||
}
|
||||
|
95
client/SDLRWwrapper.cpp
Normal file
95
client/SDLRWwrapper.cpp
Normal file
@ -0,0 +1,95 @@
|
||||
/*
|
||||
* SDLRWwrapper.cpp, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
|
||||
#include "StdInc.h"
|
||||
#include "SDLRWwrapper.h"
|
||||
#include "../lib/filesystem/CInputStream.h"
|
||||
#include <SDL_rwops.h>
|
||||
|
||||
static inline CInputStream* get_stream(SDL_RWops* context)
|
||||
{
|
||||
return static_cast<CInputStream*>(context->hidden.unknown.data1);
|
||||
}
|
||||
|
||||
static Sint64 impl_size(SDL_RWops* context)
|
||||
{
|
||||
return get_stream(context)->getSize();
|
||||
}
|
||||
|
||||
static Sint64 impl_seek(SDL_RWops* context, Sint64 offset, int whence)
|
||||
{
|
||||
auto stream = get_stream(context);
|
||||
switch (whence)
|
||||
{
|
||||
case RW_SEEK_SET:
|
||||
return stream->seek(offset);
|
||||
break;
|
||||
case RW_SEEK_CUR:
|
||||
return stream->seek(stream->tell() + offset);
|
||||
break;
|
||||
case RW_SEEK_END:
|
||||
return stream->seek(stream->getSize() + offset);
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static std::size_t impl_read(SDL_RWops* context, void *ptr, size_t size, size_t maxnum)
|
||||
{
|
||||
auto stream = get_stream(context);
|
||||
auto oldpos = stream->tell();
|
||||
|
||||
auto count = stream->read(static_cast<ui8*>(ptr), size*maxnum);
|
||||
|
||||
if (count != 0 && count != size*maxnum)
|
||||
{
|
||||
// if not a whole amount of objects of size has been read, we need to seek
|
||||
stream->seek(oldpos + size * (count / size));
|
||||
}
|
||||
|
||||
return count / size;
|
||||
}
|
||||
|
||||
static std::size_t impl_write(SDL_RWops* context, const void *ptr, size_t size, size_t num)
|
||||
{
|
||||
// writing is not supported
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int impl_close(SDL_RWops* context)
|
||||
{
|
||||
if (context == nullptr)
|
||||
return 0;
|
||||
|
||||
delete get_stream(context);
|
||||
SDL_FreeRW(context);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
SDL_RWops* MakeSDLRWops(std::unique_ptr<CInputStream> in)
|
||||
{
|
||||
SDL_RWops* result = SDL_AllocRW();
|
||||
if (!result)
|
||||
return nullptr;
|
||||
|
||||
result->size = &impl_size;
|
||||
result->seek = &impl_seek;
|
||||
result->read = &impl_read;
|
||||
result->write = &impl_write;
|
||||
result->close = &impl_close;
|
||||
|
||||
result->type = SDL_RWOPS_UNKNOWN;
|
||||
result->hidden.unknown.data1 = in.release();
|
||||
|
||||
return result;
|
||||
}
|
16
client/SDLRWwrapper.h
Normal file
16
client/SDLRWwrapper.h
Normal file
@ -0,0 +1,16 @@
|
||||
#pragma once
|
||||
|
||||
/*
|
||||
* SDLRWwrapper.h, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
|
||||
struct SDL_RWops;
|
||||
class CInputStream;
|
||||
|
||||
SDL_RWops* MakeSDLRWops(std::unique_ptr<CInputStream> in);
|
@ -6,105 +6,78 @@
|
||||
<Option pch_mode="2" />
|
||||
<Option compiler="gcc" />
|
||||
<Build>
|
||||
<Target title="Debug-win32-SDL2">
|
||||
<Target title="Debug-win32">
|
||||
<Option platforms="Windows;" />
|
||||
<Option output="../VCMI_client" prefix_auto="1" extension_auto="1" />
|
||||
<Option working_dir="../" />
|
||||
<Option object_output="../obj/Debug/" />
|
||||
<Option object_output="../obj/Client/Debug/x86" />
|
||||
<Option type="1" />
|
||||
<Option compiler="gcc" />
|
||||
<Compiler>
|
||||
<Add option="-Og" />
|
||||
<Add option="-g" />
|
||||
<Add directory="$(#sdl2.include)" />
|
||||
</Compiler>
|
||||
<Linker>
|
||||
<Add option="-lSDL2.dll" />
|
||||
<Add option="-lSDL2_image.dll" />
|
||||
<Add option="-lSDL2_mixer.dll" />
|
||||
<Add option="-lSDL2_ttf.dll" />
|
||||
<Add directory="$(#sdl2.lib)" />
|
||||
<Add directory="$(#boost.lib32)" />
|
||||
<Add directory="$(#ffmpeg.lib32)" />
|
||||
</Linker>
|
||||
</Target>
|
||||
<Target title="Release-win32-SDL2">
|
||||
<Target title="Release-win32">
|
||||
<Option platforms="Windows;" />
|
||||
<Option output="../VCMI_client" prefix_auto="1" extension_auto="1" />
|
||||
<Option working_dir="../" />
|
||||
<Option object_output="../obj/Release/" />
|
||||
<Option object_output="../obj/Client/Release/x86" />
|
||||
<Option type="1" />
|
||||
<Option compiler="gcc" />
|
||||
<Compiler>
|
||||
<Add option="-fomit-frame-pointer" />
|
||||
<Add option="-O2" />
|
||||
<Add directory="$(#sdl2.include)" />
|
||||
</Compiler>
|
||||
<Linker>
|
||||
<Add option="-s" />
|
||||
<Add option="-lSDL2.dll" />
|
||||
<Add option="-lSDL2_image.dll" />
|
||||
<Add option="-lSDL2_mixer.dll" />
|
||||
<Add option="-lSDL2_ttf.dll" />
|
||||
<Add directory="$(#sdl2.lib)" />
|
||||
<Add directory="$(#boost.lib32)" />
|
||||
<Add directory="$(#ffmpeg.lib32)" />
|
||||
</Linker>
|
||||
</Target>
|
||||
<Target title="Debug-win32-SDL1">
|
||||
<Target title="Debug-win64">
|
||||
<Option platforms="Windows;" />
|
||||
<Option output="../VCMI_client" prefix_auto="1" extension_auto="1" />
|
||||
<Option working_dir="../" />
|
||||
<Option object_output="../obj/Debug/" />
|
||||
<Option object_output="../obj/Client/Debug/x64" />
|
||||
<Option type="1" />
|
||||
<Option compiler="gcc" />
|
||||
<Option compiler="gnu_gcc_compiler_x64" />
|
||||
<Compiler>
|
||||
<Add option="-Og" />
|
||||
<Add option="-g" />
|
||||
<Add directory="$(#sdl.include)" />
|
||||
</Compiler>
|
||||
<Linker>
|
||||
<Add option="-lSDL" />
|
||||
<Add option="-lSDL_image" />
|
||||
<Add option="-lSDL_mixer" />
|
||||
<Add option="-lSDL_ttf" />
|
||||
<Add directory="$(#sdl.lib)" />
|
||||
</Linker>
|
||||
</Target>
|
||||
<Target title="Release-win32-SDL1">
|
||||
<Option platforms="Windows;" />
|
||||
<Option output="../VCMI_client" prefix_auto="1" extension_auto="1" />
|
||||
<Option working_dir="../" />
|
||||
<Option object_output="../obj/Release/" />
|
||||
<Option type="1" />
|
||||
<Option compiler="gcc" />
|
||||
<Compiler>
|
||||
<Add option="-fomit-frame-pointer" />
|
||||
<Add option="-O2" />
|
||||
<Add directory="$(#sdl.include)" />
|
||||
</Compiler>
|
||||
<Linker>
|
||||
<Add option="-s" />
|
||||
<Add option="-lSDL" />
|
||||
<Add option="-lSDL_image" />
|
||||
<Add option="-lSDL_mixer" />
|
||||
<Add option="-lSDL_ttf" />
|
||||
<Add directory="$(#sdl.lib)" />
|
||||
<Add directory="$(#sdl2.lib64)" />
|
||||
<Add directory="$(#boost.lib64)" />
|
||||
<Add directory="$(#ffmpeg.lib64)" />
|
||||
</Linker>
|
||||
</Target>
|
||||
</Build>
|
||||
<Compiler>
|
||||
<Add option="-Wextra" />
|
||||
<Add option="-Wall" />
|
||||
<Add option="-std=gnu++11" />
|
||||
<Add option="-fexceptions" />
|
||||
<Add option="-Wpointer-arith" />
|
||||
<Add option="-Wno-switch" />
|
||||
<Add option="-Wno-sign-compare" />
|
||||
<Add option="-Wno-unused-parameter" />
|
||||
<Add option="-Wno-overloaded-virtual" />
|
||||
<Add option="-fpermissive" />
|
||||
<Add option="-isystem $(#boost.include)" />
|
||||
<Add option="-DBOOST_THREAD_USE_LIB" />
|
||||
<Add option="-DBOOST_SYSTEM_NO_DEPRECATED" />
|
||||
<Add option="-D_WIN32_WINNT=0x0501" />
|
||||
<Add directory="$(#boost.include)" />
|
||||
<Add directory="../include" />
|
||||
<Add option="-D_WIN32" />
|
||||
<Add directory="../client" />
|
||||
<Add directory="$(#ffmpeg.include)" />
|
||||
<Add directory="$(#sdl2.include)" />
|
||||
<Add directory="../include" />
|
||||
</Compiler>
|
||||
<Linker>
|
||||
<Add option="-lole32" />
|
||||
@ -120,9 +93,11 @@
|
||||
<Add option="-lavformat.dll" />
|
||||
<Add option="-lswscale.dll" />
|
||||
<Add option="-lavutil.dll" />
|
||||
<Add directory="$(#boost.lib32)" />
|
||||
<Add option="-lSDL2.dll" />
|
||||
<Add option="-lSDL2_image.dll" />
|
||||
<Add option="-lSDL2_mixer.dll" />
|
||||
<Add option="-lSDL2_ttf.dll" />
|
||||
<Add directory="../" />
|
||||
<Add directory="$(#ffmpeg.lib)" />
|
||||
</Linker>
|
||||
<Unit filename="../CCallback.cpp" />
|
||||
<Unit filename="../CCallback.h" />
|
||||
@ -150,7 +125,10 @@
|
||||
<Unit filename="Graphics.h" />
|
||||
<Unit filename="NetPacksClient.cpp" />
|
||||
<Unit filename="SDLMain.h" />
|
||||
<Unit filename="SDLRWwrapper.cpp" />
|
||||
<Unit filename="SDLRWwrapper.h" />
|
||||
<Unit filename="StdInc.h">
|
||||
<Option compile="1" />
|
||||
<Option weight="0" />
|
||||
</Unit>
|
||||
<Unit filename="VCMI_client.rc">
|
||||
|
@ -203,6 +203,7 @@
|
||||
<ClCompile Include="gui\SDL_Extensions.cpp" />
|
||||
<ClCompile Include="mapHandler.cpp" />
|
||||
<ClCompile Include="NetPacksClient.cpp" />
|
||||
<ClCompile Include="SDLRWwrapper.cpp" />
|
||||
<ClCompile Include="StdInc.cpp">
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='RD|Win32'">Create</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
@ -256,6 +257,7 @@
|
||||
<ClInclude Include="mapHandler.h" />
|
||||
<ClInclude Include="resource.h" />
|
||||
<ClInclude Include="SDLMain.h" />
|
||||
<ClInclude Include="SDLRWwrapper.h" />
|
||||
<ClInclude Include="StdInc.h" />
|
||||
<ClInclude Include="widgets\AdventureMapClasses.h" />
|
||||
<ClInclude Include="widgets\Buttons.h" />
|
||||
|
@ -233,8 +233,9 @@ std::string CDefenceAnimation::getMySound()
|
||||
if(killed)
|
||||
return battle_sound(stack->getCreature(), killed);
|
||||
|
||||
if (stack->valOfBonuses(Selector::durationType(Bonus::STACK_GETS_TURN)))
|
||||
if (vstd::contains(stack->state, EBattleStackState::DEFENDING_ANIM))
|
||||
return battle_sound(stack->getCreature(), defend);
|
||||
|
||||
return battle_sound(stack->getCreature(), wince);
|
||||
}
|
||||
|
||||
@ -242,9 +243,10 @@ CCreatureAnim::EAnimType CDefenceAnimation::getMyAnimType()
|
||||
{
|
||||
if(killed)
|
||||
return CCreatureAnim::DEATH;
|
||||
|
||||
if (stack->valOfBonuses(Selector::durationType(Bonus::STACK_GETS_TURN).And(Selector::typeSubtype(Bonus::PRIMARY_SKILL, PrimarySkill::DEFENSE))))
|
||||
|
||||
if (vstd::contains(stack->state, EBattleStackState::DEFENDING_ANIM))
|
||||
return CCreatureAnim::DEFENCE;
|
||||
|
||||
return CCreatureAnim::HITTED;
|
||||
}
|
||||
|
||||
@ -281,7 +283,9 @@ void CDefenceAnimation::endAnim()
|
||||
|
||||
CDummyAnimation::CDummyAnimation(CBattleInterface * _owner, int howManyFrames)
|
||||
: CBattleAnimation(_owner), counter(0), howMany(howManyFrames)
|
||||
{}
|
||||
{
|
||||
logAnim->debugStream() << "Created dummy animation for " << howManyFrames <<" frames";
|
||||
}
|
||||
|
||||
bool CDummyAnimation::init()
|
||||
{
|
||||
@ -357,7 +361,7 @@ bool CMeleeAttackAnimation::init()
|
||||
group = mutPosToGroup[mutPos];
|
||||
break;
|
||||
default:
|
||||
logGlobal->errorStream()<<"Critical Error! Wrong dest in stackAttacking! dest: "<<dest<<" attacking stack pos: "<<attackingStackPosBeforeReturn<<" mutual pos: "<<mutPos;
|
||||
logGlobal->errorStream()<<"Critical Error! Wrong dest in stackAttacking! dest: "<<dest<<" attacking stack pos: "<<attackingStackPosBeforeReturn<<" mutual pos: "<<mutPos;
|
||||
group = CCreatureAnim::ATTACK_FRONT;
|
||||
break;
|
||||
}
|
||||
@ -778,7 +782,7 @@ bool CShootingAnimation::init()
|
||||
spi.catapultInfo.reset(new CatapultProjectileInfo(Point(spi.x, spi.y), destPos));
|
||||
|
||||
double animSpeed = AnimationControls::getProjectileSpeed() / 10;
|
||||
spi.lastStep = abs((destPos.x - spi.x) / animSpeed);
|
||||
spi.lastStep = std::abs((destPos.x - spi.x) / animSpeed);
|
||||
spi.dx = animSpeed;
|
||||
spi.dy = 0;
|
||||
|
||||
|
@ -59,8 +59,8 @@ protected:
|
||||
const CStack *attackingStack;
|
||||
int attackingStackPosBeforeReturn; //for stacks with return_after_strike feature
|
||||
public:
|
||||
void nextFrame();
|
||||
void endAnim();
|
||||
void nextFrame() override;
|
||||
void endAnim() override;
|
||||
bool checkInitialConditions();
|
||||
|
||||
CAttackAnimation(CBattleInterface *_owner, const CStack *attacker, BattleHex _dest, const CStack *defender);
|
||||
@ -80,9 +80,9 @@ class CDefenceAnimation : public CBattleStackAnimation
|
||||
|
||||
float timeToWait; // for how long this animation should be paused
|
||||
public:
|
||||
bool init();
|
||||
void nextFrame();
|
||||
void endAnim();
|
||||
bool init() override;
|
||||
void nextFrame() override;
|
||||
void endAnim() override;
|
||||
|
||||
CDefenceAnimation(StackAttackedInfo _attackedInfo, CBattleInterface * _owner);
|
||||
virtual ~CDefenceAnimation(){};
|
||||
@ -94,9 +94,9 @@ private:
|
||||
int counter;
|
||||
int howMany;
|
||||
public:
|
||||
bool init();
|
||||
void nextFrame();
|
||||
void endAnim();
|
||||
bool init() override;
|
||||
void nextFrame() override;
|
||||
void endAnim() override;
|
||||
|
||||
CDummyAnimation(CBattleInterface * _owner, int howManyFrames);
|
||||
virtual ~CDummyAnimation(){}
|
||||
@ -106,8 +106,8 @@ public:
|
||||
class CMeleeAttackAnimation : public CAttackAnimation
|
||||
{
|
||||
public:
|
||||
bool init();
|
||||
void endAnim();
|
||||
bool init() override;
|
||||
void endAnim() override;
|
||||
|
||||
CMeleeAttackAnimation(CBattleInterface * _owner, const CStack * attacker, BattleHex _dest, const CStack * _attacked);
|
||||
virtual ~CMeleeAttackAnimation(){};
|
||||
@ -133,9 +133,9 @@ private:
|
||||
public:
|
||||
BattleHex nextHex; // next hex, to which creature move right now
|
||||
|
||||
bool init();
|
||||
void nextFrame();
|
||||
void endAnim();
|
||||
bool init() override;
|
||||
void nextFrame() override;
|
||||
void endAnim() override;
|
||||
|
||||
CMovementAnimation(CBattleInterface *_owner, const CStack *_stack, std::vector<BattleHex> _destTiles, int _distance);
|
||||
virtual ~CMovementAnimation(){};
|
||||
@ -147,8 +147,8 @@ class CMovementEndAnimation : public CBattleStackAnimation
|
||||
private:
|
||||
BattleHex destinationTile;
|
||||
public:
|
||||
bool init();
|
||||
void endAnim();
|
||||
bool init() override;
|
||||
void endAnim() override;
|
||||
|
||||
CMovementEndAnimation(CBattleInterface * _owner, const CStack * _stack, BattleHex destTile);
|
||||
virtual ~CMovementEndAnimation(){};
|
||||
@ -158,8 +158,8 @@ public:
|
||||
class CMovementStartAnimation : public CBattleStackAnimation
|
||||
{
|
||||
public:
|
||||
bool init();
|
||||
void endAnim();
|
||||
bool init() override;
|
||||
void endAnim() override;
|
||||
|
||||
CMovementStartAnimation(CBattleInterface * _owner, const CStack * _stack);
|
||||
virtual ~CMovementStartAnimation(){};
|
||||
@ -171,12 +171,12 @@ class CReverseAnimation : public CBattleStackAnimation
|
||||
BattleHex hex;
|
||||
public:
|
||||
bool priority; //true - high, false - low
|
||||
bool init();
|
||||
bool init() override;
|
||||
|
||||
static void rotateStack(CBattleInterface * owner, const CStack * stack, BattleHex hex);
|
||||
|
||||
void setupSecondPart();
|
||||
void endAnim();
|
||||
void endAnim() override;
|
||||
|
||||
CReverseAnimation(CBattleInterface * _owner, const CStack * stack, BattleHex dest, bool _priority);
|
||||
virtual ~CReverseAnimation(){};
|
||||
@ -204,9 +204,9 @@ class CShootingAnimation : public CAttackAnimation
|
||||
private:
|
||||
int catapultDamage;
|
||||
public:
|
||||
bool init();
|
||||
void nextFrame();
|
||||
void endAnim();
|
||||
bool init() override;
|
||||
void nextFrame() override;
|
||||
void endAnim() override;
|
||||
|
||||
//last two params only for catapult attacks
|
||||
CShootingAnimation(CBattleInterface * _owner, const CStack * attacker, BattleHex _dest,
|
||||
@ -225,9 +225,9 @@ private:
|
||||
bool Vflip;
|
||||
bool alignToBottom;
|
||||
public:
|
||||
bool init();
|
||||
void nextFrame();
|
||||
void endAnim();
|
||||
bool init() override;
|
||||
void nextFrame() override;
|
||||
void endAnim() override;
|
||||
|
||||
CSpellEffectAnimation(CBattleInterface * _owner, ui32 _effect, BattleHex _destTile, int _dx = 0, int _dy = 0, bool _Vflip = false, bool _alignToBottom = false);
|
||||
CSpellEffectAnimation(CBattleInterface * _owner, std::string _customAnim, int _x, int _y, int _dx = 0, int _dy = 0, bool _Vflip = false, bool _alignToBottom = false);
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,12 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
|
||||
//#include "../../lib/CCreatureSet.h"
|
||||
#include "../../lib/ConstTransitivePtr.h" //may be reundant
|
||||
#include "../../lib/GameConstants.h"
|
||||
|
||||
#include "CBattleAnimations.h"
|
||||
|
||||
#include "../../lib/spells/CSpellHandler.h" //CSpell::TAnimation
|
||||
|
||||
/*
|
||||
* CBattleInterface.h, part of VCMI engine
|
||||
*
|
||||
@ -53,10 +53,10 @@ class CBattleGameInterface;
|
||||
/// Small struct which contains information about the id of the attacked stack, the damage dealt,...
|
||||
struct StackAttackedInfo
|
||||
{
|
||||
const CStack * defender; //attacked stack
|
||||
const CStack *defender; //attacked stack
|
||||
unsigned int dmg; //damage dealt
|
||||
unsigned int amountKilled; //how many creatures in stack has been killed
|
||||
const CStack * attacker; //attacking stack
|
||||
const CStack *attacker; //attacking stack
|
||||
bool indirectAttack; //if true, stack was attacked indirectly - spell or ranged attack
|
||||
bool killed; //if true, stack has been killed
|
||||
bool rebirth; //if true, play rebirth animation after all
|
||||
@ -69,7 +69,7 @@ struct BattleEffect
|
||||
int x, y; //position on the screen
|
||||
float currentFrame;
|
||||
int maxFrame;
|
||||
CDefHandler * anim; //animation to display
|
||||
CDefHandler *anim; //animation to display
|
||||
int effectID; //uniqueID equal ot ID of appropriate CSpellEffectAnim
|
||||
BattleHex position; //Indicates if effect which hex the effect is drawn on
|
||||
};
|
||||
@ -77,9 +77,9 @@ struct BattleEffect
|
||||
struct BattleObjectsByHex
|
||||
{
|
||||
typedef std::vector<int> TWallList;
|
||||
typedef std::vector<const CStack * > TStackList;
|
||||
typedef std::vector<const CStack *> TStackList;
|
||||
typedef std::vector<const BattleEffect *> TEffectList;
|
||||
typedef std::vector<shared_ptr<const CObstacleInstance> > TObstacleList;
|
||||
typedef std::vector<std::shared_ptr<const CObstacleInstance>> TObstacleList;
|
||||
|
||||
struct HexData
|
||||
{
|
||||
@ -114,23 +114,24 @@ class CBattleInterface : public CIntObject
|
||||
INVALID = -1, CREATURE_INFO,
|
||||
MOVE_TACTICS, CHOOSE_TACTICS_STACK,
|
||||
MOVE_STACK, ATTACK, WALK_AND_ATTACK, ATTACK_AND_RETURN, SHOOT, //OPEN_GATE, //we can open castle gate during siege
|
||||
NO_LOCATION, ANY_LOCATION, FRIENDLY_CREATURE_SPELL, HOSTILE_CREATURE_SPELL, RISING_SPELL, ANY_CREATURE, OBSTACLE, TELEPORT, SACRIFICE, RANDOM_GENIE_SPELL,
|
||||
NO_LOCATION, ANY_LOCATION, OBSTACLE, TELEPORT, SACRIFICE, RANDOM_GENIE_SPELL,
|
||||
FREE_LOCATION, //used with Force Field and Fire Wall - all tiles affected by spell must be free
|
||||
CATAPULT, HEAL, RISE_DEMONS
|
||||
CATAPULT, HEAL, RISE_DEMONS,
|
||||
AIMED_SPELL_CREATURE
|
||||
};
|
||||
private:
|
||||
SDL_Surface * background, * menu, * amountNormal, * amountNegative, * amountPositive, * amountEffNeutral, * cellBorders, * backgroundWithHexes;
|
||||
CButton * bOptions, * bSurrender, * bFlee, * bAutofight, * bSpell,
|
||||
* bWait, * bDefence, * bConsoleUp, * bConsoleDown, *btactNext, *btactEnd;
|
||||
CBattleConsole * console;
|
||||
CBattleHero * attackingHero, * defendingHero; //fighting heroes
|
||||
SDL_Surface *background, *menu, *amountNormal, *amountNegative, *amountPositive, *amountEffNeutral, *cellBorders, *backgroundWithHexes;
|
||||
CButton *bOptions, *bSurrender, *bFlee, *bAutofight, *bSpell,
|
||||
* bWait, *bDefence, *bConsoleUp, *bConsoleDown, *btactNext, *btactEnd;
|
||||
CBattleConsole *console;
|
||||
CBattleHero *attackingHero, *defendingHero; //fighting heroes
|
||||
CStackQueue *queue;
|
||||
const CCreatureSet *army1, *army2; //copy of initial armies (for result window)
|
||||
const CGHeroInstance * attackingHeroInstance, * defendingHeroInstance;
|
||||
std::map< int, CCreatureAnimation * > creAnims; //animations of creatures from fighting armies (order by BattleInfo's stacks' ID)
|
||||
std::map< int, CDefHandler * > idToProjectile; //projectiles of creatures (creatureID, defhandler)
|
||||
std::map< int, CDefHandler * > idToObstacle; //obstacles located on the battlefield
|
||||
std::map< int, SDL_Surface * > idToAbsoluteObstacle; //obstacles located on the battlefield
|
||||
const CGHeroInstance *attackingHeroInstance, *defendingHeroInstance;
|
||||
std::map<int, CCreatureAnimation *> creAnims; //animations of creatures from fighting armies (order by BattleInfo's stacks' ID)
|
||||
std::map<int, CDefHandler *> idToProjectile; //projectiles of creatures (creatureID, defhandler)
|
||||
std::map<int, CDefHandler *> idToObstacle; //obstacles located on the battlefield
|
||||
std::map<int, SDL_Surface *> idToAbsoluteObstacle; //obstacles located on the battlefield
|
||||
|
||||
//TODO these should be loaded only when needed (and freed then) but I believe it's rather work for resource manager,
|
||||
//so I didn't implement that (having ongoing RM development)
|
||||
@ -139,28 +140,27 @@ private:
|
||||
CDefHandler *fireWall;
|
||||
CDefHandler *smallForceField[2], *bigForceField[2]; // [side]
|
||||
|
||||
std::map< int, bool > creDir; // <creatureID, if false reverse creature's animation> //TODO: move it to battle callback
|
||||
std::map<int, bool> creDir; // <creatureID, if false reverse creature's animation> //TODO: move it to battle callback
|
||||
ui8 animCount;
|
||||
const CStack * activeStack; //number of active stack; nullptr - no one
|
||||
const CStack * mouseHoveredStack; // stack below mouse pointer, used for border animation
|
||||
const CStack * stackToActivate; //when animation is playing, we should wait till the end to make the next stack active; nullptr of none
|
||||
const CStack * selectedStack; //for Teleport / Sacrifice
|
||||
const CStack *activeStack; //number of active stack; nullptr - no one
|
||||
const CStack *mouseHoveredStack; // stack below mouse pointer, used for border animation
|
||||
const CStack *stackToActivate; //when animation is playing, we should wait till the end to make the next stack active; nullptr of none
|
||||
const CStack *selectedStack; //for Teleport / Sacrifice
|
||||
void activateStack(); //sets activeStack to stackToActivate etc. //FIXME: No, it's not clear at all
|
||||
std::vector<BattleHex> occupyableHexes, //hexes available for active stack
|
||||
attackableHexes; //hexes attackable by active stack
|
||||
bool stackCountOutsideHexes[GameConstants::BFIELD_SIZE]; // hexes that when in front of a unit cause it's amount box to move back
|
||||
bool stackCountOutsideHexes[GameConstants::BFIELD_SIZE]; // hexes that when in front of a unit cause it's amount box to move back
|
||||
BattleHex previouslyHoveredHex; //number of hex that was hovered by the cursor a while ago
|
||||
BattleHex currentlyHoveredHex; //number of hex that is supposed to be hovered (for a while it may be inappropriately set, but will be renewed soon)
|
||||
int attackingHex; //hex from which the stack would perform attack with current cursor
|
||||
|
||||
shared_ptr<CPlayerInterface> tacticianInterface; //used during tactics mode, points to the interface of player with higher tactics (can be either attacker or defender in hot-seat), valid onloy for human players
|
||||
std::shared_ptr<CPlayerInterface> tacticianInterface; //used during tactics mode, points to the interface of player with higher tactics (can be either attacker or defender in hot-seat), valid onloy for human players
|
||||
bool tacticsMode;
|
||||
bool stackCanCastSpell; //if true, active stack could possibly cats some target spell
|
||||
bool stackCanCastSpell; //if true, active stack could possibly cast some target spell
|
||||
bool creatureCasting; //if true, stack currently aims to cats a spell
|
||||
bool spellDestSelectMode; //if true, player is choosing destination for his spell - only for GUI / console
|
||||
PossibleActions spellSelMode;
|
||||
BattleAction * spellToCast; //spell for which player is choosing destination
|
||||
const CSpell * sp; //spell pointer for convenience
|
||||
BattleAction *spellToCast; //spell for which player is choosing destination
|
||||
const CSpell *sp; //spell pointer for convenience
|
||||
si32 creatureSpellToCast;
|
||||
std::vector<PossibleActions> possibleActions; //all actions possible to call at the moment by player
|
||||
std::vector<PossibleActions> localActions; //actions possible to take on hovered hex
|
||||
@ -169,15 +169,18 @@ private:
|
||||
PossibleActions selectedAction; //last action chosen (and saved) by player
|
||||
PossibleActions illegalAction; //most likely action that can't be performed here
|
||||
|
||||
void setActiveStack(const CStack * stack);
|
||||
void setHoveredStack(const CStack * stack);
|
||||
void setActiveStack(const CStack *stack);
|
||||
void setHoveredStack(const CStack *stack);
|
||||
|
||||
void requestAutofightingAIToTakeAction();
|
||||
|
||||
void getPossibleActionsForStack (const CStack * stack); //called when stack gets its turn
|
||||
void getPossibleActionsForStack (const CStack *stack, const bool forceCast); //called when stack gets its turn
|
||||
void endCastingSpell(); //ends casting spell (eg. when spell has been cast or canceled)
|
||||
|
||||
void printConsoleAttacked(const CStack * defender, int dmg, int killed, const CStack * attacker, bool Multiple);
|
||||
//force active stack to cast a spell if possible
|
||||
void enterCreatureCastingMode();
|
||||
|
||||
void printConsoleAttacked(const CStack *defender, int dmg, int killed, const CStack *attacker, bool Multiple);
|
||||
|
||||
std::list<ProjectileInfo> projectiles; //projectiles flying on battlefield
|
||||
void giveCommand(Battle::ActionType action, BattleHex tile, ui32 stackID, si32 additional=-1, si32 selectedStack = -1);
|
||||
@ -191,66 +194,83 @@ private:
|
||||
{
|
||||
private:
|
||||
SDL_Surface* walls[18];
|
||||
const CBattleInterface * owner;
|
||||
const CBattleInterface *owner;
|
||||
public:
|
||||
const CGTownInstance * town; //besieged town
|
||||
|
||||
SiegeHelper(const CGTownInstance * siegeTown, const CBattleInterface * _owner); //c-tor
|
||||
const CGTownInstance *town; //besieged town
|
||||
|
||||
SiegeHelper(const CGTownInstance *siegeTown, const CBattleInterface *_owner); //c-tor
|
||||
~SiegeHelper(); //d-tor
|
||||
|
||||
//filename getters
|
||||
//what: 0 - background, 1 - background wall, 2 - keep, 3 - bottom tower, 4 - bottom wall,
|
||||
// 5 - below gate, 6 - over gate, 7 - upper wall, 8 - upper tower, 9 - gate,
|
||||
// 10 - gate arch, 11 - bottom static 12 - upper static, 13 - moat, 14 - moat background,
|
||||
// 15 - keep battlement, 16 - bottom battlement, 17 - upper battlement;
|
||||
// state uses EWallState enum
|
||||
std::string getSiegeName(ui16 what) const;
|
||||
std::string getSiegeName(ui16 what, int state) const;
|
||||
std::string getSiegeName(ui16 what, int state) const; // state uses EWallState enum
|
||||
|
||||
void printPartOfWall(SDL_Surface * to, int what);//what: 1 - background wall, 2 - keep, 3 - bottom tower, 4 - bottom wall, 5 - below gate, 6 - over gate, 7 - upper wall, 8 - uppert tower, 9 - gate, 10 - gate arch, 11 - bottom static wall, 12 - upper static wall, 15 - keep creature cover, 16 - bottom turret creature cover, 17 - upper turret creature cover
|
||||
void printPartOfWall(SDL_Surface *to, int what);
|
||||
|
||||
enum EWallVisual
|
||||
{
|
||||
BACKGROUND = 0,
|
||||
BACKGROUND_WALL = 1,
|
||||
KEEP,
|
||||
BOTTOM_TOWER,
|
||||
BOTTOM_WALL,
|
||||
WALL_BELLOW_GATE,
|
||||
WALL_OVER_GATE,
|
||||
UPPER_WALL,
|
||||
UPPER_TOWER,
|
||||
GATE,
|
||||
GATE_ARCH,
|
||||
BOTTOM_STATIC_WALL,
|
||||
UPPER_STATIC_WALL,
|
||||
MOAT,
|
||||
BACKGROUND_MOAT,
|
||||
KEEP_BATTLEMENT,
|
||||
BOTTOM_BATTLEMENT,
|
||||
UPPER_BATTLEMENT
|
||||
};
|
||||
|
||||
friend class CBattleInterface;
|
||||
} * siegeH;
|
||||
} *siegeH;
|
||||
|
||||
shared_ptr<CPlayerInterface> attackerInt, defenderInt; //because LOCPLINT is not enough in hotSeat
|
||||
shared_ptr<CPlayerInterface> curInt; //current player interface
|
||||
const CGHeroInstance * getActiveHero(); //returns hero that can currently cast a spell
|
||||
std::shared_ptr<CPlayerInterface> attackerInt, defenderInt; //because LOCPLINT is not enough in hotSeat
|
||||
std::shared_ptr<CPlayerInterface> curInt; //current player interface
|
||||
const CGHeroInstance *getActiveHero(); //returns hero that can currently cast a spell
|
||||
|
||||
/** Methods for displaying battle screen */
|
||||
void showBackground(SDL_Surface * to);
|
||||
void showBackground(SDL_Surface *to);
|
||||
|
||||
void showBackgroundImage(SDL_Surface * to);
|
||||
void showAbsoluteObstacles(SDL_Surface * to);
|
||||
void showHighlightedHexes(SDL_Surface * to);
|
||||
void showHighlightedHex(SDL_Surface * to, BattleHex hex);
|
||||
void showInterface(SDL_Surface * to);
|
||||
void showBackgroundImage(SDL_Surface *to);
|
||||
void showAbsoluteObstacles(SDL_Surface *to);
|
||||
void showHighlightedHexes(SDL_Surface *to);
|
||||
void showHighlightedHex(SDL_Surface *to, BattleHex hex);
|
||||
void showInterface(SDL_Surface *to);
|
||||
|
||||
void showBattlefieldObjects(SDL_Surface * to);
|
||||
void showBattlefieldObjects(SDL_Surface *to);
|
||||
|
||||
void showAliveStacks(SDL_Surface * to, std::vector<const CStack *> stacks);
|
||||
void showStacks(SDL_Surface * to, std::vector<const CStack *> stacks);
|
||||
void showObstacles(SDL_Surface *to, std::vector<shared_ptr<const CObstacleInstance> > &obstacles);
|
||||
void showPiecesOfWall(SDL_Surface * to, std::vector<int> pieces);
|
||||
void showAliveStacks(SDL_Surface *to, std::vector<const CStack *> stacks);
|
||||
void showStacks(SDL_Surface *to, std::vector<const CStack *> stacks);
|
||||
void showObstacles(SDL_Surface *to, std::vector<std::shared_ptr<const CObstacleInstance>> &obstacles);
|
||||
void showPiecesOfWall(SDL_Surface *to, std::vector<int> pieces);
|
||||
|
||||
void showBattleEffects(SDL_Surface *to, const std::vector<const BattleEffect *> &battleEffects);
|
||||
void showProjectiles(SDL_Surface * to);
|
||||
void showProjectiles(SDL_Surface *to);
|
||||
|
||||
BattleObjectsByHex sortObjectsByHex();
|
||||
void updateBattleAnimations();
|
||||
|
||||
SDL_Surface *getObstacleImage(const CObstacleInstance &oi);
|
||||
Point getObstaclePosition(SDL_Surface *image, const CObstacleInstance &obstacle);
|
||||
void redrawBackgroundWithHexes(const CStack * activeStack);
|
||||
void redrawBackgroundWithHexes(const CStack *activeStack);
|
||||
/** End of battle screen blitting methods */
|
||||
|
||||
PossibleActions getCasterAction(const CSpell *spell, const ISpellCaster *caster, ECastingMode::ECastingMode mode) const;
|
||||
public:
|
||||
std::list<std::pair<CBattleAnimation *, bool> > pendingAnims; //currently displayed animations <anim, initialized>
|
||||
void addNewAnim(CBattleAnimation * anim); //adds new anim to pendingAnims
|
||||
std::list<std::pair<CBattleAnimation *, bool>> pendingAnims; //currently displayed animations <anim, initialized>
|
||||
void addNewAnim(CBattleAnimation *anim); //adds new anim to pendingAnims
|
||||
ui32 animIDhelper; //for giving IDs for animations
|
||||
static CondSh<bool> animsAreDisplayed; //for waiting with the end of battle for end of anims
|
||||
|
||||
CBattleInterface(const CCreatureSet * army1, const CCreatureSet * army2, const CGHeroInstance *hero1, const CGHeroInstance *hero2, const SDL_Rect & myRect, shared_ptr<CPlayerInterface> att, shared_ptr<CPlayerInterface> defen); //c-tor
|
||||
~CBattleInterface(); //d-tor
|
||||
CBattleInterface(const CCreatureSet *army1, const CCreatureSet *army2, const CGHeroInstance *hero1, const CGHeroInstance *hero2, const SDL_Rect & myRect, std::shared_ptr<CPlayerInterface> att, std::shared_ptr<CPlayerInterface> defen); //c-tor
|
||||
virtual ~CBattleInterface(); //d-tor
|
||||
|
||||
//std::vector<TimeInterested*> timeinterested; //animation handling
|
||||
void setPrintCellBorders(bool set); //if true, cell borders will be printed
|
||||
@ -258,18 +278,18 @@ public:
|
||||
void setPrintMouseShadow(bool set); //if true, hex under mouse will be shaded
|
||||
void setAnimSpeed(int set); //speed of animation; range 1..100
|
||||
int getAnimSpeed() const; //speed of animation; range 1..100
|
||||
CPlayerInterface * getCurrentPlayerInterface() const;
|
||||
CPlayerInterface *getCurrentPlayerInterface() const;
|
||||
|
||||
std::vector<CClickableHex*> bfield; //11 lines, 17 hexes on each
|
||||
SDL_Surface * cellBorder, * cellShade;
|
||||
SDL_Surface *cellBorder, *cellShade;
|
||||
CondSh<BattleAction *> *givenCommand; //data != nullptr if we have i.e. moved current unit
|
||||
bool myTurn; //if true, interface is active (commands can be ordered)
|
||||
CBattleResultWindow * resWindow; //window of end of battle
|
||||
CBattleResultWindow *resWindow; //window of end of battle
|
||||
|
||||
bool moveStarted; //if true, the creature that is already moving is going to make its first step
|
||||
int moveSoundHander; // sound handler used when moving a unit
|
||||
|
||||
const BattleResult * bresult; //result of a battle; if non-zero then display when all animations end
|
||||
const BattleResult *bresult; //result of a battle; if non-zero then display when all animations end
|
||||
|
||||
// block all UI elements, e.g. during enemy turn
|
||||
// unlike activate/deactivate this method will correctly grey-out all elements
|
||||
@ -291,59 +311,65 @@ public:
|
||||
void bEndTacticPhase();
|
||||
//end of button handle funcs
|
||||
//napisz tu klase odpowiadajaca za wyswietlanie bitwy i obsluge uzytkownika, polecenia ma przekazywac callbackiem
|
||||
void activate();
|
||||
void deactivate();
|
||||
void keyPressed(const SDL_KeyboardEvent & key);
|
||||
void mouseMoved(const SDL_MouseMotionEvent &sEvent);
|
||||
void clickRight(tribool down, bool previousState);
|
||||
void activate() override;
|
||||
void deactivate() override;
|
||||
void keyPressed(const SDL_KeyboardEvent & key) override;
|
||||
void mouseMoved(const SDL_MouseMotionEvent &sEvent) override;
|
||||
void clickRight(tribool down, bool previousState) override;
|
||||
|
||||
void show(SDL_Surface *to);
|
||||
void showAll(SDL_Surface *to);
|
||||
void show(SDL_Surface *to) override;
|
||||
void showAll(SDL_Surface *to) override;
|
||||
|
||||
//call-ins
|
||||
void startAction(const BattleAction* action);
|
||||
void newStack(const CStack * stack); //new stack appeared on battlefield
|
||||
void newStack(const CStack *stack); //new stack appeared on battlefield
|
||||
void stackRemoved(int stackID); //stack disappeared from batlefiled
|
||||
void stackActivated(const CStack * stack); //active stack has been changed
|
||||
void stackMoved(const CStack * stack, std::vector<BattleHex> destHex, int distance); //stack with id number moved to destHex
|
||||
void stackActivated(const CStack *stack); //active stack has been changed
|
||||
void stackMoved(const CStack *stack, std::vector<BattleHex> destHex, int distance); //stack with id number moved to destHex
|
||||
void waitForAnims();
|
||||
void stacksAreAttacked(std::vector<StackAttackedInfo> attackedInfos); //called when a certain amount of stacks has been attacked
|
||||
void stackAttacking(const CStack * attacker, BattleHex dest, const CStack * attacked, bool shooting); //called when stack with id ID is attacking something on hex dest
|
||||
void stackAttacking(const CStack *attacker, BattleHex dest, const CStack *attacked, bool shooting); //called when stack with id ID is attacking something on hex dest
|
||||
void newRoundFirst( int round );
|
||||
void newRound(int number); //caled when round is ended; number is the number of round
|
||||
void hexLclicked(int whichOne); //hex only call-in
|
||||
void stackIsCatapulting(const CatapultAttack & ca); //called when a stack is attacking walls
|
||||
void battleFinished(const BattleResult& br); //called when battle is finished - battleresult window should be printed
|
||||
void displayBattleFinished(); //displays battle result
|
||||
void spellCast(const BattleSpellCast * sc); //called when a hero casts a spell
|
||||
void spellCast(const BattleSpellCast *sc); //called when a hero casts a spell
|
||||
void battleStacksEffectsSet(const SetStackEffect & sse); //called when a specific effect is set to stacks
|
||||
void castThisSpell(SpellID spellID); //called when player has chosen a spell from spellbook
|
||||
void displayEffect(ui32 effect, int destTile, bool areaEffect = true); //displays custom effect on the battlefield
|
||||
void displaySpellEffect(SpellID spellID, BattleHex destinationTile, bool areaEffect = true); //displays spell`s affected animation
|
||||
void displaySpellHit(SpellID spellID, BattleHex destinationTile, bool areaEffect = true); //displays spell`s affected animation
|
||||
|
||||
void displayEffect(ui32 effect, int destTile); //displays custom effect on the battlefield
|
||||
|
||||
void displaySpellCast(SpellID spellID, BattleHex destinationTile); //displays spell`s cast animation
|
||||
void displaySpellEffect(SpellID spellID, BattleHex destinationTile); //displays spell`s affected animation
|
||||
void displaySpellHit(SpellID spellID, BattleHex destinationTile); //displays spell`s affected animation
|
||||
|
||||
void displaySpellAnimation(const CSpell::TAnimation & animation, BattleHex destinationTile);
|
||||
|
||||
void battleTriggerEffect(const BattleTriggerEffect & bte);
|
||||
void setBattleCursor(const int myNumber); //really complex and messy, sets attackingHex
|
||||
void endAction(const BattleAction* action);
|
||||
void hideQueue();
|
||||
void showQueue();
|
||||
PossibleActions selectionTypeByPositiveness(const CSpell & spell);
|
||||
|
||||
Rect hexPosition(BattleHex hex) const;
|
||||
|
||||
void handleHex(BattleHex myNumber, int eventType);
|
||||
bool isCastingPossibleHere (const CStack * sactive, const CStack * shere, BattleHex myNumber);
|
||||
bool canStackMoveHere (const CStack * sactive, BattleHex MyNumber); //TODO: move to BattleState / callback
|
||||
bool isCastingPossibleHere (const CStack *sactive, const CStack *shere, BattleHex myNumber);
|
||||
bool canStackMoveHere (const CStack *sactive, BattleHex MyNumber); //TODO: move to BattleState / callback
|
||||
|
||||
BattleHex fromWhichHexAttack(BattleHex myNumber);
|
||||
void obstaclePlaced(const CObstacleInstance & oi);
|
||||
|
||||
const CGHeroInstance * currentHero() const;
|
||||
void gateStateChanged(const EGateState state);
|
||||
|
||||
const CGHeroInstance *currentHero() const;
|
||||
InfoAboutHero enemyHero() const;
|
||||
|
||||
friend class CPlayerInterface;
|
||||
friend class CButton;
|
||||
friend class CInGameConsole;
|
||||
|
||||
|
||||
friend class CBattleResultWindow;
|
||||
friend class CBattleHero;
|
||||
friend class CSpellEffectAnimation;
|
||||
|
@ -29,6 +29,7 @@
|
||||
#include "../../lib/NetPacks.h"
|
||||
#include "../../lib/StartInfo.h"
|
||||
#include "../../lib/CondSh.h"
|
||||
#include "../../lib/mapObjects/CGTownInstance.h"
|
||||
|
||||
/*
|
||||
* CBattleInterfaceClasses.cpp, part of VCMI engine
|
||||
@ -69,6 +70,7 @@ void CBattleConsole::showAll(SDL_Surface * to)
|
||||
|
||||
bool CBattleConsole::addText(const std::string & text)
|
||||
{
|
||||
logGlobal->traceStream() <<"CBattleConsole message: "<<text;
|
||||
if(text.size()>70)
|
||||
return false; //text too long!
|
||||
int firstInToken = 0;
|
||||
@ -175,6 +177,15 @@ void CBattleHero::setPhase(int newPhase)
|
||||
nextPhase = 0;
|
||||
}
|
||||
|
||||
void CBattleHero::hover(bool on)
|
||||
{
|
||||
//TODO: Make lines below work properly
|
||||
if (on)
|
||||
CCS->curh->changeGraphic(ECursor::COMBAT, 5);
|
||||
else
|
||||
CCS->curh->changeGraphic(ECursor::COMBAT, 0);
|
||||
}
|
||||
|
||||
void CBattleHero::clickLeft(tribool down, bool previousState)
|
||||
{
|
||||
if(myOwner->spellDestSelectMode) //we are casting a spell
|
||||
@ -189,8 +200,26 @@ void CBattleHero::clickLeft(tribool down, bool previousState)
|
||||
}
|
||||
CCS->curh->changeGraphic(ECursor::ADVENTURE, 0);
|
||||
|
||||
auto spellWindow = new CSpellWindow(genRect(595, 620, (screen->w - 620)/2, (screen->h - 595)/2), myHero, myOwner->getCurrentPlayerInterface());
|
||||
GH.pushInt(spellWindow);
|
||||
GH.pushInt(new CSpellWindow(myHero, myOwner->getCurrentPlayerInterface()));
|
||||
}
|
||||
}
|
||||
|
||||
void CBattleHero::clickRight(tribool down, bool previousState)
|
||||
{
|
||||
Point windowPosition;
|
||||
windowPosition.x = (!flip) ? myOwner->pos.topLeft().x + 1 : myOwner->pos.topRight().x - 79;
|
||||
windowPosition.y = myOwner->pos.y + 135;
|
||||
|
||||
InfoAboutHero targetHero;
|
||||
|
||||
if (down && myOwner->myTurn)
|
||||
{
|
||||
if (myHero != nullptr)
|
||||
targetHero.initFromHero(myHero, InfoAboutHero::EInfoLevel::INBATTLE);
|
||||
else
|
||||
targetHero = myOwner->enemyHero();
|
||||
|
||||
GH.pushInt(new CHeroInfoWindow(targetHero, &windowPosition));
|
||||
}
|
||||
}
|
||||
|
||||
@ -245,7 +274,7 @@ CBattleHero::CBattleHero(const std::string & defName, bool flipG, PlayerColor pl
|
||||
CSDL_Ext::alphaTransform(elem.bitmap);
|
||||
graphics->blueToPlayersAdv(elem.bitmap, player);
|
||||
}
|
||||
addUsedEvents(LCLICK);
|
||||
addUsedEvents(LCLICK | RCLICK | HOVER);
|
||||
|
||||
switchToNextPhase();
|
||||
}
|
||||
@ -350,7 +379,7 @@ CBattleResultWindow::CBattleResultWindow(const BattleResult &br, const SDL_Rect
|
||||
auto heroInfo = owner.cb->battleGetHeroInfo(i);
|
||||
const int xs[] = {21, 392};
|
||||
|
||||
if(heroInfo.portrait >= 0) //attacking hero
|
||||
if(heroInfo.portrait >= 0) //attacking hero
|
||||
{
|
||||
new CAnimImage("PortraitsLarge", heroInfo.portrait, 0, xs[i], 38);
|
||||
sideNames[i] = heroInfo.name;
|
||||
@ -418,7 +447,7 @@ CBattleResultWindow::CBattleResultWindow(const BattleResult &br, const SDL_Rect
|
||||
boost::algorithm::replace_first(str,"%s",ourHero->name);
|
||||
boost::algorithm::replace_first(str,"%d",boost::lexical_cast<std::string>(br.exp[weAreAttacker?0:1]));
|
||||
}
|
||||
|
||||
|
||||
new CTextBox(str, Rect(69, 203, 330, 68), 0, FONT_SMALL, CENTER, Colors::WHITE);
|
||||
}
|
||||
else // we lose
|
||||
@ -479,7 +508,7 @@ void CBattleResultWindow::bExitf()
|
||||
if(dynamic_cast<CBattleInterface*>(GH.topInt()))
|
||||
GH.popInts(1); //pop battle interface if present
|
||||
|
||||
//Result window and battle interface are gone. We requested all dialogs to be closed before opening the battle,
|
||||
//Result window and battle interface are gone. We requested all dialogs to be closed before opening the battle,
|
||||
//so we can be sure that there is no dialogs left on GUI stack.
|
||||
intTmp.showingDialog->setn(false);
|
||||
CCS->videoh->close();
|
||||
@ -502,7 +531,7 @@ Point CClickableHex::getXYUnitAnim(BattleHex hexNum, const CStack * stack, CBatt
|
||||
break;
|
||||
case -4: //upper turret
|
||||
ret = cbi->siegeH->town->town->clientInfo.siegePositions[20];
|
||||
break;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -612,6 +641,47 @@ void CClickableHex::clickRight(tribool down, bool previousState)
|
||||
}
|
||||
}
|
||||
|
||||
CHeroInfoWindow::CHeroInfoWindow(const InfoAboutHero &hero, Point *position) : CWindowObject(RCLICK_POPUP | SHADOW_DISABLED, "CHRPOP")
|
||||
{
|
||||
OBJ_CONSTRUCTION_CAPTURING_ALL;
|
||||
if (position != nullptr)
|
||||
moveTo(*position);
|
||||
background->colorize(hero.owner); //maybe add this functionality to base class?
|
||||
|
||||
int attack = hero.details->primskills[0];
|
||||
int defense = hero.details->primskills[1];
|
||||
int power = hero.details->primskills[2];
|
||||
int knowledge = hero.details->primskills[3];
|
||||
int morale = hero.details->morale;
|
||||
int luck = hero.details->luck;
|
||||
int currentSpellPoints = hero.details->mana;
|
||||
int maxSpellPoints = hero.details->manaLimit;
|
||||
|
||||
new CAnimImage("PortraitsLarge", hero.portrait, 0, 10, 6);
|
||||
|
||||
//primary stats
|
||||
new CLabel(9, 75, EFonts::FONT_TINY, EAlignment::TOPLEFT, Colors::WHITE, CGI->generaltexth->allTexts[380] + ":");
|
||||
new CLabel(9, 87, EFonts::FONT_TINY, EAlignment::TOPLEFT, Colors::WHITE, CGI->generaltexth->allTexts[381] + ":");
|
||||
new CLabel(9, 99, EFonts::FONT_TINY, EAlignment::TOPLEFT, Colors::WHITE, CGI->generaltexth->allTexts[382] + ":");
|
||||
new CLabel(9, 111, EFonts::FONT_TINY, EAlignment::TOPLEFT, Colors::WHITE, CGI->generaltexth->allTexts[383] + ":");
|
||||
|
||||
new CLabel(69, 87, EFonts::FONT_TINY, EAlignment::BOTTOMRIGHT, Colors::WHITE, std::to_string(attack));
|
||||
new CLabel(69, 99, EFonts::FONT_TINY, EAlignment::BOTTOMRIGHT, Colors::WHITE, std::to_string(defense));
|
||||
new CLabel(69, 111, EFonts::FONT_TINY, EAlignment::BOTTOMRIGHT, Colors::WHITE, std::to_string(power));
|
||||
new CLabel(69, 123, EFonts::FONT_TINY, EAlignment::BOTTOMRIGHT, Colors::WHITE, std::to_string(knowledge));
|
||||
|
||||
//morale+luck
|
||||
new CLabel(9, 131, EFonts::FONT_TINY, EAlignment::TOPLEFT, Colors::WHITE, CGI->generaltexth->allTexts[384] + ":");
|
||||
new CLabel(9, 143, EFonts::FONT_TINY, EAlignment::TOPLEFT, Colors::WHITE, CGI->generaltexth->allTexts[385] + ":");
|
||||
|
||||
new CAnimImage("IMRL22", morale + 3, 0, 47, 131);
|
||||
new CAnimImage("ILCK22", luck + 3, 0, 47, 143);
|
||||
|
||||
//spell points
|
||||
new CLabel(39, 174, EFonts::FONT_TINY, EAlignment::CENTER, Colors::WHITE, CGI->generaltexth->allTexts[387]);
|
||||
new CLabel(39, 186, EFonts::FONT_TINY, EAlignment::CENTER, Colors::WHITE, std::to_string(currentSpellPoints) + "/" + std::to_string(maxSpellPoints));
|
||||
}
|
||||
|
||||
void CStackQueue::update()
|
||||
{
|
||||
stacksSorted.clear();
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
#include "../gui/CIntObject.h"
|
||||
#include "../../lib/BattleHex.h"
|
||||
#include "../windows/CWindowObject.h"
|
||||
|
||||
struct SDL_Surface;
|
||||
class CDefHandler;
|
||||
@ -38,7 +39,7 @@ public:
|
||||
std::string ingcAlter; //alternative text set by in-game console - very important!
|
||||
int whoSetAlter; //who set alter text; 0 - battle interface or none, 1 - button
|
||||
CBattleConsole();
|
||||
void showAll(SDL_Surface * to = 0);
|
||||
void showAll(SDL_Surface * to = 0) override;
|
||||
bool addText(const std::string &text); //adds text at the last position; returns false if failed (e.g. text longer than 70 characters)
|
||||
void alterText(const std::string &text); //place string at alterTxt
|
||||
void eraseText(ui32 pos); //erases added text at position pos
|
||||
@ -60,13 +61,21 @@ public:
|
||||
int nextPhase; //stage of animation to be set after current phase is fully displayed
|
||||
int currentFrame, firstFrame, lastFrame; //frame of animation
|
||||
ui8 flagAnim, animCount; //for flag animation
|
||||
void show(SDL_Surface * to); //prints next frame of animation to to
|
||||
void show(SDL_Surface * to) override; //prints next frame of animation to to
|
||||
void setPhase(int newPhase); //sets phase of hero animation
|
||||
void clickLeft(tribool down, bool previousState); //call-in
|
||||
void hover(bool on) override;
|
||||
void clickLeft(tribool down, bool previousState) override; //call-in
|
||||
void clickRight(tribool down, bool previousState) override; //call-in
|
||||
CBattleHero(const std::string &defName, bool filpG, PlayerColor player, const CGHeroInstance *hero, const CBattleInterface *owner); //c-tor
|
||||
~CBattleHero(); //d-tor
|
||||
};
|
||||
|
||||
class CHeroInfoWindow : public CWindowObject
|
||||
{
|
||||
public:
|
||||
CHeroInfoWindow(const InfoAboutHero &hero, Point *position);
|
||||
};
|
||||
|
||||
/// Class which manages the battle options window
|
||||
class CBattleOptionsWindow : public CIntObject
|
||||
{
|
||||
@ -96,8 +105,8 @@ public:
|
||||
|
||||
void bExitf(); //exit button callback
|
||||
|
||||
void activate();
|
||||
void show(SDL_Surface * to = 0);
|
||||
void activate() override;
|
||||
void show(SDL_Surface * to = 0) override;
|
||||
};
|
||||
|
||||
/// Class which stands for a single hex field on a battlefield
|
||||
@ -114,10 +123,10 @@ public:
|
||||
static Point getXYUnitAnim(BattleHex hexNum, const CStack * creature, CBattleInterface * cbi); //returns (x, y) of left top corner of animation
|
||||
|
||||
//for user interactions
|
||||
void hover (bool on);
|
||||
void mouseMoved (const SDL_MouseMotionEvent &sEvent);
|
||||
void clickLeft(tribool down, bool previousState);
|
||||
void clickRight(tribool down, bool previousState);
|
||||
void hover (bool on) override;
|
||||
void mouseMoved (const SDL_MouseMotionEvent &sEvent) override;
|
||||
void clickLeft(tribool down, bool previousState) override;
|
||||
void clickRight(tribool down, bool previousState) override;
|
||||
CClickableHex();
|
||||
};
|
||||
|
||||
@ -132,7 +141,7 @@ class CStackQueue : public CIntObject
|
||||
const CStack *stack;
|
||||
bool small;
|
||||
|
||||
void showAll(SDL_Surface * to);
|
||||
void showAll(SDL_Surface * to) override;
|
||||
void setStack(const CStack *nStack);
|
||||
StackBox(bool small);
|
||||
};
|
||||
@ -150,6 +159,6 @@ public:
|
||||
CStackQueue(bool Embedded, CBattleInterface * _owner);
|
||||
~CStackQueue();
|
||||
void update();
|
||||
void showAll(SDL_Surface *to);
|
||||
void showAll(SDL_Surface *to) override;
|
||||
void blitBg(SDL_Surface * to);
|
||||
};
|
||||
|
@ -8,7 +8,6 @@
|
||||
#include "../../lib/filesystem/CBinaryReader.h"
|
||||
#include "../../lib/filesystem/CMemoryStream.h"
|
||||
|
||||
#include "../gui/SDL_Extensions.h"
|
||||
#include "../gui/SDL_Pixels.h"
|
||||
|
||||
/*
|
||||
@ -164,7 +163,9 @@ CCreatureAnimation::CCreatureAnimation(std::string name, TSpeedController contro
|
||||
pixelDataSize = data.second;
|
||||
}
|
||||
|
||||
CBinaryReader reader(new CMemoryStream(pixelData.get(), pixelDataSize));
|
||||
CMemoryStream stm(pixelData.get(), pixelDataSize);
|
||||
|
||||
CBinaryReader reader(&stm);
|
||||
|
||||
reader.readInt32(); // def type, unused
|
||||
|
||||
@ -178,7 +179,7 @@ CCreatureAnimation::CCreatureAnimation(std::string name, TSpeedController contro
|
||||
elem.r = reader.readUInt8();
|
||||
elem.g = reader.readUInt8();
|
||||
elem.b = reader.readUInt8();
|
||||
CSDL_Ext::colorSetAlpha(elem,0);
|
||||
elem.a = SDL_ALPHA_OPAQUE;
|
||||
}
|
||||
|
||||
for (int i=0; i<totalBlocks; i++)
|
||||
@ -267,11 +268,7 @@ static SDL_Color genShadow(ui8 alpha)
|
||||
|
||||
static SDL_Color genBorderColor(ui8 alpha, const SDL_Color & base)
|
||||
{
|
||||
#ifdef VCMI_SDL1
|
||||
return CSDL_Ext::makeColor(base.r, base.g, base.b, ui8(base.unused * alpha / 256));
|
||||
#else
|
||||
return CSDL_Ext::makeColor(base.r, base.g, base.b, ui8(base.a * alpha / 256));
|
||||
#endif
|
||||
}
|
||||
|
||||
static ui8 mixChannels(ui8 c1, ui8 c2, ui8 a1, ui8 a2)
|
||||
@ -281,22 +278,12 @@ static ui8 mixChannels(ui8 c1, ui8 c2, ui8 a1, ui8 a2)
|
||||
|
||||
static SDL_Color addColors(const SDL_Color & base, const SDL_Color & over)
|
||||
{
|
||||
#ifdef VCMI_SDL1
|
||||
return CSDL_Ext::makeColor(
|
||||
mixChannels(over.r, base.r, over.unused, base.unused),
|
||||
mixChannels(over.g, base.g, over.unused, base.unused),
|
||||
mixChannels(over.b, base.b, over.unused, base.unused),
|
||||
ui8(over.unused + base.unused * (255 - over.unused) / 256)
|
||||
);
|
||||
#else
|
||||
return CSDL_Ext::makeColor(
|
||||
mixChannels(over.r, base.r, over.a, base.a),
|
||||
mixChannels(over.g, base.g, over.a, base.a),
|
||||
mixChannels(over.b, base.b, over.a, base.a),
|
||||
ui8(over.a + base.a * (255 - over.a) / 256)
|
||||
);
|
||||
|
||||
#endif // VCMI_SDL1
|
||||
}
|
||||
|
||||
std::array<SDL_Color, 8> CCreatureAnimation::genSpecialPalette()
|
||||
@ -322,7 +309,9 @@ void CCreatureAnimation::nextFrameT(SDL_Surface * dest, bool rotate)
|
||||
|
||||
ui32 offset = dataOffsets.at(type).at(floor(currentFrame));
|
||||
|
||||
CBinaryReader reader(new CMemoryStream(pixelData.get(), pixelDataSize));
|
||||
CMemoryStream stm(pixelData.get(), pixelDataSize);
|
||||
|
||||
CBinaryReader reader(&stm);
|
||||
|
||||
reader.getStream()->seek(offset);
|
||||
|
||||
@ -397,7 +386,7 @@ void CCreatureAnimation::nextFrame(SDL_Surface *dest, bool attacker)
|
||||
case 3: return nextFrameT<3>(dest, !attacker);
|
||||
case 4: return nextFrameT<4>(dest, !attacker);
|
||||
default:
|
||||
logGlobal->errorStream() << (int)dest->format->BitsPerPixel << " bpp is not supported!!!";
|
||||
logGlobal->errorStream() << (int)dest->format->BitsPerPixel << " bpp is not supported!!!";
|
||||
}
|
||||
}
|
||||
|
||||
@ -427,11 +416,7 @@ inline void CCreatureAnimation::putPixel(ui8 * dest, const SDL_Color & color, si
|
||||
if (index < 8)
|
||||
{
|
||||
const SDL_Color & pal = special[index];
|
||||
#ifdef VCMI_SDL1
|
||||
ColorPutter<bpp, 0>::PutColor(dest, pal.r, pal.g, pal.b, pal.unused);
|
||||
#else
|
||||
ColorPutter<bpp, 0>::PutColor(dest, pal.r, pal.g, pal.b, pal.a);
|
||||
#endif // 0
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -66,7 +66,7 @@ private:
|
||||
|
||||
//animation raw data
|
||||
//TODO: use vector instead?
|
||||
unique_ptr<ui8[]> pixelData;
|
||||
std::unique_ptr<ui8[]> pixelData;
|
||||
size_t pixelDataSize;
|
||||
|
||||
// speed of animation, measure in frames per second
|
||||
|
@ -51,11 +51,11 @@ class CompImageLoader
|
||||
ui8 *position;
|
||||
ui8 *entry;
|
||||
ui32 currentLine;
|
||||
|
||||
|
||||
inline ui8 typeOf(ui8 color);
|
||||
inline void NewEntry(ui8 color, size_t size);
|
||||
inline void NewEntry(const ui8 * &data, size_t size);
|
||||
|
||||
|
||||
public:
|
||||
//load size raw pixels from data
|
||||
inline void Load(size_t size, const ui8 * data);
|
||||
@ -75,29 +75,26 @@ class CFileCache
|
||||
static const int cacheSize = 50; //Max number of cached files
|
||||
struct FileData
|
||||
{
|
||||
ResourceID name;
|
||||
size_t size;
|
||||
ui8 * data;
|
||||
ResourceID name;
|
||||
size_t size;
|
||||
std::unique_ptr<ui8[]> data;
|
||||
|
||||
ui8 * getCopy()
|
||||
std::unique_ptr<ui8[]> getCopy()
|
||||
{
|
||||
auto ret = new ui8[size];
|
||||
std::copy(data, data + size, ret);
|
||||
auto ret = std::unique_ptr<ui8[]>(new ui8[size]);
|
||||
std::copy(data.get(), data.get() + size, ret.get());
|
||||
return ret;
|
||||
}
|
||||
FileData():
|
||||
size(0),
|
||||
data(nullptr)
|
||||
FileData(ResourceID name_, size_t size_, std::unique_ptr<ui8[]> data_):
|
||||
name{std::move(name_)},
|
||||
size{size_},
|
||||
data{std::move(data_)}
|
||||
{}
|
||||
~FileData()
|
||||
{
|
||||
delete [] data;
|
||||
}
|
||||
};
|
||||
|
||||
std::list<FileData> cache;
|
||||
std::deque<FileData> cache;
|
||||
public:
|
||||
ui8 * getCachedFile(ResourceID && rid)
|
||||
std::unique_ptr<ui8[]> getCachedFile(ResourceID rid)
|
||||
{
|
||||
for(auto & file : cache)
|
||||
{
|
||||
@ -107,12 +104,10 @@ public:
|
||||
// Still here? Cache miss
|
||||
if (cache.size() > cacheSize)
|
||||
cache.pop_front();
|
||||
cache.push_back(FileData());
|
||||
|
||||
auto data = CResourceHandler::get()->load(rid)->readAll();
|
||||
cache.back().name = ResourceID(rid);
|
||||
cache.back().size = data.second;
|
||||
cache.back().data = data.first.release();
|
||||
|
||||
cache.emplace_back(std::move(rid), data.second, std::move(data.first));
|
||||
|
||||
return cache.back().getCopy();
|
||||
}
|
||||
@ -132,8 +127,8 @@ CDefFile::CDefFile(std::string Name):
|
||||
static SDL_Color H3Palette[8] =
|
||||
{
|
||||
{ 0, 0, 0, 0},// 100% - transparency
|
||||
{ 0, 0, 0, 64},// 75% - shadow border,
|
||||
{ 0, 0, 0, 128},// TODO: find exact value
|
||||
{ 0, 0, 0, 32},// 75% - shadow border,
|
||||
{ 0, 0, 0, 64},// TODO: find exact value
|
||||
{ 0, 0, 0, 128},// TODO: for transparency
|
||||
{ 0, 0, 0, 128},// 50% - shadow body
|
||||
{ 0, 0, 0, 0},// 100% - selection highlight
|
||||
@ -142,15 +137,15 @@ CDefFile::CDefFile(std::string Name):
|
||||
};
|
||||
data = animationCache.getCachedFile(ResourceID(std::string("SPRITES/") + Name, EResType::ANIMATION));
|
||||
|
||||
palette = new SDL_Color[256];
|
||||
palette = std::unique_ptr<SDL_Color[]>(new SDL_Color[256]);
|
||||
int it = 0;
|
||||
|
||||
ui32 type = read_le_u32(data + it);
|
||||
ui32 type = read_le_u32(data.get() + it);
|
||||
it+=4;
|
||||
//int width = read_le_u32(data + it); it+=4;//not used
|
||||
//int height = read_le_u32(data + it); it+=4;
|
||||
it+=8;
|
||||
ui32 totalBlocks = read_le_u32(data + it);
|
||||
ui32 totalBlocks = read_le_u32(data.get() + it);
|
||||
it+=4;
|
||||
|
||||
for (ui32 i= 0; i<256; i++)
|
||||
@ -158,18 +153,18 @@ CDefFile::CDefFile(std::string Name):
|
||||
palette[i].r = data[it++];
|
||||
palette[i].g = data[it++];
|
||||
palette[i].b = data[it++];
|
||||
CSDL_Ext::colorSetAlpha(palette[i],255);
|
||||
palette[i].a = SDL_ALPHA_OPAQUE;
|
||||
}
|
||||
if (type == 71 || type == 64)//Buttons/buildings don't have shadows\semi-transparency
|
||||
memset(palette, 0, sizeof(SDL_Color)*2);
|
||||
memset(palette.get(), 0, sizeof(SDL_Color)*2);
|
||||
else
|
||||
memcpy(palette, H3Palette, sizeof(SDL_Color)*8);//initialize shadow\selection colors
|
||||
memcpy(palette.get(), H3Palette, sizeof(SDL_Color)*8);//initialize shadow\selection colors
|
||||
|
||||
for (ui32 i=0; i<totalBlocks; i++)
|
||||
{
|
||||
size_t blockID = read_le_u32(data + it);
|
||||
size_t blockID = read_le_u32(data.get() + it);
|
||||
it+=4;
|
||||
size_t totalEntries = read_le_u32(data + it);
|
||||
size_t totalEntries = read_le_u32(data.get() + it);
|
||||
it+=12;
|
||||
//8 unknown bytes - skipping
|
||||
|
||||
@ -178,7 +173,7 @@ CDefFile::CDefFile(std::string Name):
|
||||
|
||||
for (ui32 j=0; j<totalEntries; j++)
|
||||
{
|
||||
size_t currOffset = read_le_u32(data + it);
|
||||
size_t currOffset = read_le_u32(data.get() + it);
|
||||
offset[blockID].push_back(currOffset);
|
||||
it += 4;
|
||||
}
|
||||
@ -192,7 +187,7 @@ void CDefFile::loadFrame(size_t frame, size_t group, ImageLoader &loader) const
|
||||
it = offset.find(group);
|
||||
assert (it != offset.end());
|
||||
|
||||
const ui8 * FDef = data+it->second[frame];
|
||||
const ui8 * FDef = data.get()+it->second[frame];
|
||||
|
||||
const SSpriteDef sd = * reinterpret_cast<const SSpriteDef *>(FDef);
|
||||
SSpriteDef sprite;
|
||||
@ -210,7 +205,7 @@ void CDefFile::loadFrame(size_t frame, size_t group, ImageLoader &loader) const
|
||||
|
||||
loader.init(Point(sprite.width, sprite.height),
|
||||
Point(sprite.leftMargin, sprite.topMargin),
|
||||
Point(sprite.fullWidth, sprite.fullHeight), palette);
|
||||
Point(sprite.fullWidth, sprite.fullHeight), palette.get());
|
||||
|
||||
switch (sprite.format)
|
||||
{
|
||||
@ -274,7 +269,7 @@ void CDefFile::loadFrame(size_t frame, size_t group, ImageLoader &loader) const
|
||||
|
||||
if (code==7)//Raw data
|
||||
{
|
||||
loader.Load(length, FDef[currentOffset]);
|
||||
loader.Load(length, FDef + currentOffset);
|
||||
currentOffset += length;
|
||||
}
|
||||
else//RLE
|
||||
@ -316,16 +311,12 @@ void CDefFile::loadFrame(size_t frame, size_t group, ImageLoader &loader) const
|
||||
break;
|
||||
}
|
||||
default:
|
||||
logGlobal->errorStream()<<"Error: unsupported format of def file: "<<sprite.format;
|
||||
logGlobal->errorStream()<<"Error: unsupported format of def file: "<<sprite.format;
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
CDefFile::~CDefFile()
|
||||
{
|
||||
delete[] data;
|
||||
delete[] palette;
|
||||
}
|
||||
CDefFile::~CDefFile() = default;
|
||||
|
||||
const std::map<size_t, size_t > CDefFile::getEntries() const
|
||||
{
|
||||
@ -355,7 +346,11 @@ void SDLImageLoader::init(Point SpriteSize, Point Margins, Point FullSize, SDL_C
|
||||
image->fullSize = FullSize;
|
||||
|
||||
//Prepare surface
|
||||
SDL_SetColors(image->surf, pal, 0, 256);
|
||||
SDL_Palette * p = SDL_AllocPalette(256);
|
||||
SDL_SetPaletteColors(p, pal, 0, 256);
|
||||
SDL_SetSurfacePalette(image->surf, p);
|
||||
SDL_FreePalette(p);
|
||||
|
||||
SDL_LockSurface(image->surf);
|
||||
lineStart = position = (ui8*)image->surf->pixels;
|
||||
}
|
||||
@ -387,19 +382,19 @@ inline void SDLImageLoader::EndLine()
|
||||
SDLImageLoader::~SDLImageLoader()
|
||||
{
|
||||
SDL_UnlockSurface(image->surf);
|
||||
SDL_SetColorKey(image->surf, SDL_SRCCOLORKEY, 0);
|
||||
SDL_SetColorKey(image->surf, SDL_TRUE, 0);
|
||||
//TODO: RLE if compressed and bpp>1
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
CompImageLoader::CompImageLoader(CompImage * Img):
|
||||
image(Img),
|
||||
position(nullptr),
|
||||
entry(nullptr),
|
||||
currentLine(0)
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
|
||||
void CompImageLoader::init(Point SpriteSize, Point Margins, Point FullSize, SDL_Color *pal)
|
||||
@ -444,14 +439,10 @@ inline ui8 CompImageLoader::typeOf(ui8 color)
|
||||
{
|
||||
if (color == 0)
|
||||
return 0;
|
||||
#ifdef VCMI_SDL1
|
||||
if (image->palette[color].unused != 255)
|
||||
return 1;
|
||||
#else
|
||||
|
||||
if (image->palette[color].a != 255)
|
||||
return 1;
|
||||
#endif // 0
|
||||
|
||||
|
||||
return 2;
|
||||
}
|
||||
|
||||
@ -489,7 +480,7 @@ inline void CompImageLoader::Load(size_t size, const ui8 * data)
|
||||
ui8 type = typeOf(color);
|
||||
ui8 color2;
|
||||
ui8 type2;
|
||||
|
||||
|
||||
if (size > 1)
|
||||
{
|
||||
do
|
||||
@ -616,7 +607,7 @@ SDLImage::SDLImage(std::string filename, bool compressed):
|
||||
|
||||
if (surf == nullptr)
|
||||
{
|
||||
logGlobal->errorStream() << "Error: failed to load image "<<filename;
|
||||
logGlobal->errorStream() << "Error: failed to load image "<<filename;
|
||||
return;
|
||||
}
|
||||
else
|
||||
@ -628,22 +619,11 @@ SDLImage::SDLImage(std::string filename, bool compressed):
|
||||
{
|
||||
SDL_Surface *temp = surf;
|
||||
// add RLE flag
|
||||
#ifdef VCMI_SDL1
|
||||
if (surf->format->palette)
|
||||
{
|
||||
const SDL_Color &c = temp->format->palette->colors[0];
|
||||
SDL_SetColorKey(temp, (SDL_SRCCOLORKEY | SDL_RLEACCEL),
|
||||
SDL_MapRGB(temp -> format, c.r, c.g, c.b));
|
||||
}
|
||||
else
|
||||
SDL_SetColorKey(temp, SDL_RLEACCEL, 0);
|
||||
#else
|
||||
if (surf->format->palette)
|
||||
{
|
||||
CSDL_Ext::setColorKey(temp,temp->format->palette->colors[0]);
|
||||
}
|
||||
SDL_SetSurfaceRLE(temp, SDL_RLEACCEL);
|
||||
#endif
|
||||
SDL_SetSurfaceRLE(temp, SDL_RLEACCEL);
|
||||
|
||||
// convert surface to enable RLE
|
||||
surf = SDL_ConvertSurface(temp, temp->format, temp->flags);
|
||||
@ -651,10 +631,11 @@ SDLImage::SDLImage(std::string filename, bool compressed):
|
||||
}
|
||||
}
|
||||
|
||||
void SDLImage::draw(SDL_Surface *where, int posX, int posY, Rect *src, ui8 rotation) const
|
||||
void SDLImage::draw(SDL_Surface *where, int posX, int posY, Rect *src, ui8 alpha) const
|
||||
{
|
||||
if (!surf)
|
||||
return;
|
||||
|
||||
Rect sourceRect(margins.x, margins.y, surf->w, surf->h);
|
||||
//TODO: rotation and scaling
|
||||
if (src)
|
||||
@ -664,7 +645,21 @@ void SDLImage::draw(SDL_Surface *where, int posX, int posY, Rect *src, ui8 rotat
|
||||
Rect destRect(posX, posY, surf->w, surf->h);
|
||||
destRect += sourceRect.topLeft();
|
||||
sourceRect -= margins;
|
||||
CSDL_Ext::blitSurface(surf, &sourceRect, where, &destRect);
|
||||
|
||||
if(surf->format->BitsPerPixel == 8)
|
||||
{
|
||||
CSDL_Ext::blit8bppAlphaTo24bpp(surf, &sourceRect, where, &destRect);
|
||||
}
|
||||
else if(surf->format->Amask == 0)
|
||||
{
|
||||
SDL_BlitSurface(surf, &sourceRect, where, &destRect);
|
||||
}
|
||||
else
|
||||
{
|
||||
SDL_SetSurfaceBlendMode(surf, SDL_BLENDMODE_BLEND);
|
||||
SDL_BlitSurface(surf, &sourceRect, where, &destRect);
|
||||
SDL_SetSurfaceBlendMode(surf, SDL_BLENDMODE_NONE);
|
||||
}
|
||||
}
|
||||
|
||||
void SDLImage::playerColored(PlayerColor player)
|
||||
@ -691,7 +686,7 @@ CompImage::CompImage(const CDefFile *data, size_t frame, size_t group):
|
||||
surf(nullptr),
|
||||
line(nullptr),
|
||||
palette(nullptr)
|
||||
|
||||
|
||||
{
|
||||
CompImageLoader loader(this);
|
||||
data->loadFrame(frame, group, loader);
|
||||
@ -749,7 +744,7 @@ void CompImage::draw(SDL_Surface *where, int posX, int posY, Rect *src, ui8 alph
|
||||
|
||||
currX = 0;
|
||||
ui8 bpp = where->format->BytesPerPixel;
|
||||
|
||||
|
||||
//Calculate position for blitting: pixels + Y + X
|
||||
ui8* blitPos = (ui8*) where->pixels;
|
||||
if (rotation & 4)
|
||||
@ -780,7 +775,7 @@ void CompImage::draw(SDL_Surface *where, int posX, int posY, Rect *src, ui8 alph
|
||||
void CompImage::BlitBlockWithBpp(ui8 bpp, ui8 type, ui8 size, ui8 *&data, ui8 *&dest, ui8 alpha, bool rotated) const
|
||||
{
|
||||
assert(bpp>1 && bpp<5);
|
||||
|
||||
|
||||
if (rotated)
|
||||
switch (bpp)
|
||||
{
|
||||
@ -811,21 +806,13 @@ void CompImage::BlitBlock(ui8 type, ui8 size, ui8 *&data, ui8 *&dest, ui8 alpha)
|
||||
for (size_t i=0; i<size; i++)
|
||||
{
|
||||
SDL_Color col = palette[*(data++)];
|
||||
#ifdef VCMI_SDL1
|
||||
col.unused = (ui32)col.unused*alpha/255;
|
||||
#else
|
||||
col.a = (ui32)col.a*alpha/255;
|
||||
#endif // 0
|
||||
ColorPutter<bpp, 1>::PutColorAlpha(dest, col);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef VCMI_SDL1
|
||||
if (palette[color].unused == 255)
|
||||
#else
|
||||
|
||||
if (palette[color].a == 255)
|
||||
#endif // 0
|
||||
{
|
||||
//Put row of RGB data
|
||||
for (size_t i=0; i<size; i++)
|
||||
@ -836,25 +823,12 @@ void CompImage::BlitBlock(ui8 type, ui8 size, ui8 *&data, ui8 *&dest, ui8 alpha)
|
||||
//Put row of RGBA data
|
||||
for (size_t i=0; i<size; i++)
|
||||
ColorPutter<bpp, 1>::PutColorAlpha(dest, palette[*(data++)]);
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
//RLE-d sequence
|
||||
else
|
||||
{
|
||||
#ifdef VCMI_SDL1
|
||||
if (alpha != 255 && palette[type].unused !=0)//Per-surface alpha is set
|
||||
{
|
||||
SDL_Color col = palette[type];
|
||||
col.unused = (int)col.unused*(255-alpha)/255;
|
||||
for (size_t i=0; i<size; i++)
|
||||
ColorPutter<bpp, 1>::PutColorAlpha(dest, col);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (palette[type].unused)
|
||||
|
||||
#else
|
||||
if (alpha != 255 && palette[type].a !=0)//Per-surface alpha is set
|
||||
{
|
||||
SDL_Color col = palette[type];
|
||||
@ -863,9 +837,8 @@ void CompImage::BlitBlock(ui8 type, ui8 size, ui8 *&data, ui8 *&dest, ui8 alpha)
|
||||
ColorPutter<bpp, 1>::PutColorAlpha(dest, col);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
switch (palette[type].a)
|
||||
#endif // 0
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
@ -991,7 +964,7 @@ bool CAnimation::loadFrame(CDefFile * file, size_t frame, size_t group)
|
||||
else //load from separate file
|
||||
{
|
||||
std::string filename = source[group][frame].Struct().find("file")->second.String();
|
||||
|
||||
|
||||
IImage * img = getFromExtraDef(filename);
|
||||
if (!img)
|
||||
img = new SDLImage(filename, compressed);
|
||||
@ -1092,13 +1065,14 @@ CDefFile * CAnimation::getFile() const
|
||||
|
||||
void CAnimation::printError(size_t frame, size_t group, std::string type) const
|
||||
{
|
||||
logGlobal->errorStream() << type <<" error: Request for frame not present in CAnimation! "
|
||||
<<"\tFile name: "<<name<<" Group: "<<group<<" Frame: "<<frame;
|
||||
logGlobal->errorStream() << type << " error: Request for frame not present in CAnimation! "
|
||||
<< "\tFile name: " << name << " Group: " << group << " Frame: " << frame;
|
||||
}
|
||||
|
||||
CAnimation::CAnimation(std::string Name, bool Compressed):
|
||||
name(Name),
|
||||
compressed(Compressed)
|
||||
compressed(Compressed),
|
||||
preloaded(false)
|
||||
{
|
||||
size_t dotPos = name.find_last_of('.');
|
||||
if ( dotPos!=-1 )
|
||||
@ -1107,27 +1081,28 @@ CAnimation::CAnimation(std::string Name, bool Compressed):
|
||||
CDefFile * file = getFile();
|
||||
init(file);
|
||||
delete file;
|
||||
loadedAnims.insert(this);
|
||||
}
|
||||
|
||||
CAnimation::CAnimation():
|
||||
name(""),
|
||||
compressed(false)
|
||||
compressed(false),
|
||||
preloaded(false)
|
||||
{
|
||||
init(nullptr);
|
||||
loadedAnims.insert(this);
|
||||
}
|
||||
|
||||
CAnimation::~CAnimation()
|
||||
{
|
||||
if (!images.empty())
|
||||
if(preloaded)
|
||||
unload();
|
||||
|
||||
if(!images.empty())
|
||||
{
|
||||
logGlobal->warnStream()<<"Warning: not all frames were unloaded from "<<name;
|
||||
logGlobal->warnStream()<<"Warning: not all frames were unloaded from "<<name;
|
||||
for (auto & elem : images)
|
||||
for (auto & _image : elem.second)
|
||||
delete _image.second;
|
||||
}
|
||||
loadedAnims.erase(this);
|
||||
}
|
||||
|
||||
void CAnimation::setCustom(std::string filename, size_t frame, size_t group)
|
||||
@ -1171,6 +1146,12 @@ void CAnimation::unload()
|
||||
|
||||
}
|
||||
|
||||
void CAnimation::preload()
|
||||
{
|
||||
preloaded = true;
|
||||
load();
|
||||
}
|
||||
|
||||
void CAnimation::loadGroup(size_t group)
|
||||
{
|
||||
CDefFile * file = getFile();
|
||||
@ -1209,21 +1190,6 @@ size_t CAnimation::size(size_t group) const
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::set<CAnimation*> CAnimation::loadedAnims;
|
||||
|
||||
void CAnimation::getAnimInfo()
|
||||
{
|
||||
logGlobal->errorStream()<<"Animation stats: Loaded "<<loadedAnims.size()<<" total";
|
||||
for (auto anim : loadedAnims)
|
||||
{
|
||||
|
||||
logGlobal->errorStream()<<"Name: "<<anim->name<<" Groups: "<<anim->images.size();
|
||||
if (!anim->images.empty())
|
||||
logGlobal->errorStream()<<", "<<anim->images.begin()->second.size()<<" image loaded in group "<< anim->images.begin()->first;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
float CFadeAnimation::initialCounter() const
|
||||
{
|
||||
if (fadingMode == EMode::OUT)
|
||||
@ -1235,12 +1201,12 @@ void CFadeAnimation::update()
|
||||
{
|
||||
if (!fading)
|
||||
return;
|
||||
|
||||
|
||||
if (fadingMode == EMode::OUT)
|
||||
fadingCounter -= delta;
|
||||
else
|
||||
fadingCounter += delta;
|
||||
|
||||
|
||||
if (isFinished())
|
||||
{
|
||||
fading = false;
|
||||
@ -1269,7 +1235,7 @@ CFadeAnimation::CFadeAnimation()
|
||||
CFadeAnimation::~CFadeAnimation()
|
||||
{
|
||||
if (fadingSurface && shouldFreeSurface)
|
||||
SDL_FreeSurface(fadingSurface);
|
||||
SDL_FreeSurface(fadingSurface);
|
||||
}
|
||||
|
||||
void CFadeAnimation::init(EMode mode, SDL_Surface * sourceSurface, bool freeSurfaceAtEnd /* = false */, float animDelta /* = DEFAULT_DELTA */)
|
||||
@ -1280,17 +1246,17 @@ void CFadeAnimation::init(EMode mode, SDL_Surface * sourceSurface, bool freeSurf
|
||||
// (alternatively, we could just return here to ignore the new fade request until this one finished (but we'd need to free the passed bitmap to avoid leaks))
|
||||
logGlobal->warnStream() << "Tried to init fading animation that is already running.";
|
||||
if (fadingSurface && shouldFreeSurface)
|
||||
SDL_FreeSurface(fadingSurface);
|
||||
}
|
||||
SDL_FreeSurface(fadingSurface);
|
||||
}
|
||||
if (animDelta <= 0.0f)
|
||||
{
|
||||
logGlobal->warnStream() << "Fade anim: delta should be positive; " << animDelta << " given.";
|
||||
animDelta = DEFAULT_DELTA;
|
||||
}
|
||||
|
||||
|
||||
if (sourceSurface)
|
||||
fadingSurface = sourceSurface;
|
||||
|
||||
|
||||
delta = animDelta;
|
||||
fadingMode = mode;
|
||||
fadingCounter = initialCounter();
|
||||
@ -1299,13 +1265,13 @@ void CFadeAnimation::init(EMode mode, SDL_Surface * sourceSurface, bool freeSurf
|
||||
}
|
||||
|
||||
void CFadeAnimation::draw(SDL_Surface * targetSurface, const SDL_Rect * sourceRect, SDL_Rect * destRect)
|
||||
{
|
||||
{
|
||||
if (!fading || !fadingSurface || fadingMode == EMode::NONE)
|
||||
{
|
||||
fading = false;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
CSDL_Ext::setAlpha(fadingSurface, fadingCounter * 255);
|
||||
SDL_BlitSurface(fadingSurface, const_cast<SDL_Rect *>(sourceRect), targetSurface, destRect); //FIXME
|
||||
CSDL_Ext::setAlpha(fadingSurface, 255);
|
||||
|
@ -39,8 +39,8 @@ private:
|
||||
//offset[group][frame] - offset of frame data in file
|
||||
std::map<size_t, std::vector <size_t> > offset;
|
||||
|
||||
ui8 * data;
|
||||
SDL_Color * palette;
|
||||
std::unique_ptr<ui8[]> data;
|
||||
std::unique_ptr<SDL_Color[]> palette;
|
||||
|
||||
public:
|
||||
CDefFile(std::string Name);
|
||||
@ -98,10 +98,11 @@ public:
|
||||
SDLImage(SDL_Surface * from, bool extraRef);
|
||||
~SDLImage();
|
||||
|
||||
void draw(SDL_Surface *where, int posX=0, int posY=0, Rect *src=nullptr, ui8 alpha=255) const;
|
||||
void playerColored(PlayerColor player);
|
||||
int width() const;
|
||||
int height() const;
|
||||
void draw(SDL_Surface *where, int posX=0, int posY=0, Rect *src=nullptr, ui8 alpha=255) const override;
|
||||
|
||||
void playerColored(PlayerColor player) override;
|
||||
int width() const override;
|
||||
int height() const override;
|
||||
|
||||
friend class SDLImageLoader;
|
||||
};
|
||||
@ -144,10 +145,10 @@ public:
|
||||
CompImage(SDL_Surface * surf);
|
||||
~CompImage();
|
||||
|
||||
void draw(SDL_Surface *where, int posX=0, int posY=0, Rect *src=nullptr, ui8 alpha=255) const;
|
||||
void playerColored(PlayerColor player);
|
||||
int width() const;
|
||||
int height() const;
|
||||
void draw(SDL_Surface *where, int posX=0, int posY=0, Rect *src=nullptr, ui8 alpha=255) const override;
|
||||
void playerColored(PlayerColor player) override;
|
||||
int width() const override;
|
||||
int height() const override;
|
||||
|
||||
friend class CompImageLoader;
|
||||
};
|
||||
@ -169,6 +170,8 @@ private:
|
||||
//if true all frames will be stored in compressed (RLE) state
|
||||
const bool compressed;
|
||||
|
||||
bool preloaded;
|
||||
|
||||
//loader, will be called by load(), require opened def file for loading from it. Returns true if image is loaded
|
||||
bool loadFrame(CDefFile * file, size_t frame, size_t group);
|
||||
|
||||
@ -195,10 +198,6 @@ public:
|
||||
CAnimation();
|
||||
~CAnimation();
|
||||
|
||||
//static method for debugging - print info about loaded animations
|
||||
static void getAnimInfo();
|
||||
static std::set<CAnimation*> loadedAnims;
|
||||
|
||||
//add custom surface to the selected position.
|
||||
void setCustom(std::string filename, size_t frame, size_t group=0);
|
||||
|
||||
@ -208,6 +207,7 @@ public:
|
||||
//all available frames
|
||||
void load ();
|
||||
void unload();
|
||||
void preload();
|
||||
|
||||
//all frames from group
|
||||
void loadGroup (size_t group);
|
||||
@ -236,7 +236,7 @@ private:
|
||||
bool fading;
|
||||
float fadingCounter;
|
||||
bool shouldFreeSurface;
|
||||
|
||||
|
||||
float initialCounter() const;
|
||||
bool isFinished() const;
|
||||
public:
|
||||
|
@ -27,10 +27,8 @@ void CCursorHandler::initCursor()
|
||||
currentCursor = nullptr;
|
||||
|
||||
help = CSDL_Ext::newSurface(40,40);
|
||||
#ifndef VCMI_SDL1
|
||||
//No blending. Ensure, that we are copying pixels during "screen restore draw"
|
||||
SDL_SetSurfaceBlendMode(help,SDL_BLENDMODE_NONE);
|
||||
#endif // VCMI_SDL1
|
||||
SDL_ShowCursor(SDL_DISABLE);
|
||||
|
||||
changeGraphic(ECursor::ADVENTURE, 0);
|
||||
|
@ -1,5 +1,6 @@
|
||||
#include "StdInc.h"
|
||||
#include "CGuiHandler.h"
|
||||
#include "../lib/CondSh.h"
|
||||
|
||||
#include <SDL.h>
|
||||
|
||||
@ -15,9 +16,10 @@
|
||||
extern std::queue<SDL_Event> events;
|
||||
extern boost::mutex eventsM;
|
||||
|
||||
CondSh<bool> CGuiHandler::terminate_cond;
|
||||
boost::thread_specific_ptr<bool> inGuiThread;
|
||||
|
||||
SObjectConstruction::SObjectConstruction( CIntObject *obj )
|
||||
SObjectConstruction::SObjectConstruction(CIntObject *obj)
|
||||
:myObj(obj)
|
||||
{
|
||||
GH.createdObj.push_front(obj);
|
||||
@ -63,10 +65,7 @@ void CGuiHandler::processLists(const ui16 activityFlag, std::function<void (std:
|
||||
processList(CIntObject::TIME,activityFlag,&timeinterested,cb);
|
||||
processList(CIntObject::WHEEL,activityFlag,&wheelInterested,cb);
|
||||
processList(CIntObject::DOUBLECLICK,activityFlag,&doubleClickInterested,cb);
|
||||
|
||||
#ifndef VCMI_SDL1
|
||||
processList(CIntObject::TEXTINPUT,activityFlag,&textInterested,cb);
|
||||
#endif // VCMI_SDL1
|
||||
}
|
||||
|
||||
void CGuiHandler::handleElementActivate(CIntObject * elem, ui16 activityFlag)
|
||||
@ -87,7 +86,7 @@ void CGuiHandler::handleElementDeActivate(CIntObject * elem, ui16 activityFlag)
|
||||
elem->active_m &= ~activityFlag;
|
||||
}
|
||||
|
||||
void CGuiHandler::popInt( IShowActivatable *top )
|
||||
void CGuiHandler::popInt(IShowActivatable *top)
|
||||
{
|
||||
assert(listInt.front() == top);
|
||||
top->deactivate();
|
||||
@ -98,7 +97,7 @@ void CGuiHandler::popInt( IShowActivatable *top )
|
||||
totalRedraw();
|
||||
}
|
||||
|
||||
void CGuiHandler::popIntTotally( IShowActivatable *top )
|
||||
void CGuiHandler::popIntTotally(IShowActivatable *top)
|
||||
{
|
||||
assert(listInt.front() == top);
|
||||
popInt(top);
|
||||
@ -106,7 +105,7 @@ void CGuiHandler::popIntTotally( IShowActivatable *top )
|
||||
fakeMouseMove();
|
||||
}
|
||||
|
||||
void CGuiHandler::pushInt( IShowActivatable *newInt )
|
||||
void CGuiHandler::pushInt(IShowActivatable *newInt)
|
||||
{
|
||||
assert(newInt);
|
||||
assert(boost::range::find(listInt, newInt) == listInt.end()); // do not add same object twice
|
||||
@ -122,7 +121,7 @@ void CGuiHandler::pushInt( IShowActivatable *newInt )
|
||||
totalRedraw();
|
||||
}
|
||||
|
||||
void CGuiHandler::popInts( int howMany )
|
||||
void CGuiHandler::popInts(int howMany)
|
||||
{
|
||||
if(!howMany) return; //senseless but who knows...
|
||||
|
||||
@ -196,10 +195,8 @@ void CGuiHandler::handleEvent(SDL_Event *sEvent)
|
||||
//translate numpad keys
|
||||
if(key.keysym.sym == SDLK_KP_ENTER)
|
||||
{
|
||||
key.keysym.sym = (SDLKey)SDLK_RETURN;
|
||||
#ifndef VCMI_SDL1
|
||||
key.keysym.sym = SDLK_RETURN;
|
||||
key.keysym.scancode = SDL_SCANCODE_RETURN;
|
||||
#endif // VCMI_SDL1
|
||||
}
|
||||
|
||||
bool keysCaptured = false;
|
||||
@ -270,27 +267,18 @@ void CGuiHandler::handleEvent(SDL_Event *sEvent)
|
||||
}
|
||||
}
|
||||
}
|
||||
#ifdef VCMI_SDL1 //SDL1x only events
|
||||
else if(sEvent->button.button == SDL_BUTTON_WHEELDOWN || sEvent->button.button == SDL_BUTTON_WHEELUP)
|
||||
{
|
||||
std::list<CIntObject*> hlp = wheelInterested;
|
||||
for(auto i=hlp.begin(); i != hlp.end() && current; i++)
|
||||
{
|
||||
if(!vstd::contains(wheelInterested,*i)) continue;
|
||||
(*i)->wheelScrolled(sEvent->button.button == SDL_BUTTON_WHEELDOWN, isItIn(&(*i)->pos,sEvent->motion.x,sEvent->motion.y));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#ifndef VCMI_SDL1 //SDL2x only events
|
||||
else if (sEvent->type == SDL_MOUSEWHEEL)
|
||||
{
|
||||
std::list<CIntObject*> hlp = wheelInterested;
|
||||
for(auto i=hlp.begin(); i != hlp.end() && current; i++)
|
||||
{
|
||||
if(!vstd::contains(wheelInterested,*i)) continue;
|
||||
(*i)->wheelScrolled(sEvent->wheel.y < 0, isItIn(&(*i)->pos,sEvent->motion.x,sEvent->motion.y));
|
||||
}
|
||||
// SDL doesn't have the proper values for mouse positions on SDL_MOUSEWHEEL, refetch them
|
||||
int x = 0, y = 0;
|
||||
SDL_GetMouseState(&x, &y);
|
||||
(*i)->wheelScrolled(sEvent->wheel.y < 0, isItIn(&(*i)->pos, x, y));
|
||||
}
|
||||
}
|
||||
else if(sEvent->type == SDL_TEXTINPUT)
|
||||
{
|
||||
@ -307,7 +295,6 @@ void CGuiHandler::handleEvent(SDL_Event *sEvent)
|
||||
}
|
||||
}
|
||||
//todo: muiltitouch
|
||||
#endif // VCMI_SDL1
|
||||
else if ((sEvent->type==SDL_MOUSEBUTTONUP) && (sEvent->button.button == SDL_BUTTON_LEFT))
|
||||
{
|
||||
std::list<CIntObject*> hlp = lclickable;
|
||||
@ -341,7 +328,6 @@ void CGuiHandler::handleEvent(SDL_Event *sEvent)
|
||||
}
|
||||
}
|
||||
current = nullptr;
|
||||
|
||||
} //event end
|
||||
|
||||
void CGuiHandler::handleMouseMotion(SDL_Event *sEvent)
|
||||
@ -378,7 +364,7 @@ void CGuiHandler::simpleRedraw()
|
||||
objsToBlit.back()->show(screen); //blit active interface/window
|
||||
}
|
||||
|
||||
void CGuiHandler::handleMoveInterested( const SDL_MouseMotionEvent & motion )
|
||||
void CGuiHandler::handleMoveInterested(const SDL_MouseMotionEvent & motion)
|
||||
{
|
||||
//sending active, MotionInterested objects mouseMoved() call
|
||||
std::list<CIntObject*> miCopy = motioninterested;
|
||||
@ -394,12 +380,9 @@ void CGuiHandler::handleMoveInterested( const SDL_MouseMotionEvent & motion )
|
||||
void CGuiHandler::fakeMouseMove()
|
||||
{
|
||||
SDL_Event evnt;
|
||||
#ifdef VCMI_SDL1
|
||||
SDL_MouseMotionEvent sme = {SDL_MOUSEMOTION, 0, 0, 0, 0, 0, 0};
|
||||
#else
|
||||
SDL_MouseMotionEvent sme = {SDL_MOUSEMOTION, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||
#endif
|
||||
int x, y;
|
||||
|
||||
sme.state = SDL_GetMouseState(&x, &y);
|
||||
sme.x = x;
|
||||
sme.y = y;
|
||||
@ -411,29 +394,37 @@ void CGuiHandler::fakeMouseMove()
|
||||
|
||||
void CGuiHandler::renderFrame()
|
||||
{
|
||||
auto doUpdate = [this]()
|
||||
|
||||
// Updating GUI requires locking pim mutex (that protects screen and GUI state).
|
||||
// During game:
|
||||
// When ending the game, the pim mutex might be hold by other thread,
|
||||
// that will notify us about the ending game by setting terminate_cond flag.
|
||||
//in PreGame terminate_cond stay false
|
||||
|
||||
bool acquiredTheLockOnPim = false; //for tracking whether pim mutex locking succeeded
|
||||
while(!terminate_cond.get() && !(acquiredTheLockOnPim = CPlayerInterface::pim->try_lock())) //try acquiring long until it succeeds or we are told to terminate
|
||||
boost::this_thread::sleep(boost::posix_time::milliseconds(15));
|
||||
|
||||
if(acquiredTheLockOnPim)
|
||||
{
|
||||
// If we are here, pim mutex has been successfully locked - let's store it in a safe RAII lock.
|
||||
boost::unique_lock<boost::recursive_mutex> un(*CPlayerInterface::pim, boost::adopt_lock);
|
||||
|
||||
if(nullptr != curInt)
|
||||
{
|
||||
curInt -> update();
|
||||
}
|
||||
curInt->update();
|
||||
|
||||
if (settings["general"]["showfps"].Bool())
|
||||
drawFPSCounter();
|
||||
|
||||
// draw the mouse cursor and update the screen
|
||||
CCS->curh->render();
|
||||
|
||||
#ifndef VCMI_SDL1
|
||||
if(0 != SDL_RenderCopy(mainRenderer, screenTexture, nullptr, nullptr))
|
||||
logGlobal->errorStream() << __FUNCTION__ << " SDL_RenderCopy " << SDL_GetError();
|
||||
|
||||
SDL_RenderPresent(mainRenderer);
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
if(curInt)
|
||||
curInt->runLocked(doUpdate);
|
||||
else
|
||||
doUpdate();
|
||||
|
||||
SDL_RenderPresent(mainRenderer);
|
||||
}
|
||||
|
||||
mainFPSmng->framerateDelay(); // holds a constant FPS
|
||||
}
|
||||
|
||||
@ -448,6 +439,8 @@ CGuiHandler::CGuiHandler()
|
||||
// Creates the FPS manager and sets the framerate to 48 which is doubled the value of the original Heroes 3 FPS rate
|
||||
mainFPSmng = new CFramerateManager(48);
|
||||
//do not init CFramerateManager here --AVS
|
||||
|
||||
terminate_cond.set(false);
|
||||
}
|
||||
|
||||
CGuiHandler::~CGuiHandler()
|
||||
@ -470,23 +463,8 @@ void CGuiHandler::drawFPSCounter()
|
||||
graphics->fonts[FONT_BIG]->renderTextLeft(screen, fps, yellow, Point(10, 10));
|
||||
}
|
||||
|
||||
SDLKey CGuiHandler::arrowToNum( SDLKey key )
|
||||
SDL_Keycode CGuiHandler::arrowToNum(SDL_Keycode key)
|
||||
{
|
||||
#ifdef VCMI_SDL1
|
||||
switch(key)
|
||||
{
|
||||
case SDLK_DOWN:
|
||||
return SDLK_KP2;
|
||||
case SDLK_UP:
|
||||
return SDLK_KP8;
|
||||
case SDLK_LEFT:
|
||||
return SDLK_KP4;
|
||||
case SDLK_RIGHT:
|
||||
return SDLK_KP6;
|
||||
default:
|
||||
throw std::runtime_error("Wrong key!");assert(0);
|
||||
}
|
||||
#else
|
||||
switch(key)
|
||||
{
|
||||
case SDLK_DOWN:
|
||||
@ -500,20 +478,14 @@ SDLKey CGuiHandler::arrowToNum( SDLKey key )
|
||||
default:
|
||||
throw std::runtime_error("Wrong key!");
|
||||
}
|
||||
#endif // 0
|
||||
}
|
||||
|
||||
SDLKey CGuiHandler::numToDigit( SDLKey key )
|
||||
SDL_Keycode CGuiHandler::numToDigit(SDL_Keycode key)
|
||||
{
|
||||
#ifdef VCMI_SDL1
|
||||
if(key >= SDLK_KP0 && key <= SDLK_KP9)
|
||||
return SDLKey(key - SDLK_KP0 + SDLK_0);
|
||||
#endif // 0
|
||||
|
||||
#define REMOVE_KP(keyName) case SDLK_KP_ ## keyName : return SDLK_ ## keyName;
|
||||
switch(key)
|
||||
{
|
||||
#ifndef VCMI_SDL1
|
||||
REMOVE_KP(0)
|
||||
REMOVE_KP(1)
|
||||
REMOVE_KP(2)
|
||||
@ -524,7 +496,6 @@ SDLKey CGuiHandler::numToDigit( SDLKey key )
|
||||
REMOVE_KP(7)
|
||||
REMOVE_KP(8)
|
||||
REMOVE_KP(9)
|
||||
#endif // VCMI_SDL1
|
||||
REMOVE_KP(PERIOD)
|
||||
REMOVE_KP(MINUS)
|
||||
REMOVE_KP(PLUS)
|
||||
@ -542,22 +513,15 @@ SDLKey CGuiHandler::numToDigit( SDLKey key )
|
||||
#undef REMOVE_KP
|
||||
}
|
||||
|
||||
bool CGuiHandler::isNumKey( SDLKey key, bool number )
|
||||
bool CGuiHandler::isNumKey(SDL_Keycode key, bool number)
|
||||
{
|
||||
#ifdef VCMI_SDL1
|
||||
if(number)
|
||||
return key >= SDLK_KP0 && key <= SDLK_KP9;
|
||||
else
|
||||
return key >= SDLK_KP0 && key <= SDLK_KP_EQUALS;
|
||||
#else
|
||||
if(number)
|
||||
return key >= SDLK_KP_1 && key <= SDLK_KP_0;
|
||||
else
|
||||
return (key >= SDLK_KP_1 && key <= SDLK_KP_0) || key == SDLK_KP_MINUS || key == SDLK_KP_PLUS || key == SDLK_KP_EQUALS;
|
||||
#endif // 0
|
||||
}
|
||||
|
||||
bool CGuiHandler::isArrowKey( SDLKey key )
|
||||
bool CGuiHandler::isArrowKey(SDL_Keycode key)
|
||||
{
|
||||
return key == SDLK_UP || key == SDLK_DOWN || key == SDLK_LEFT || key == SDLK_RIGHT;
|
||||
}
|
||||
@ -580,6 +544,8 @@ CFramerateManager::CFramerateManager(int rate)
|
||||
this->rate = rate;
|
||||
this->rateticks = (1000.0 / rate);
|
||||
this->fps = 0;
|
||||
this->accumulatedFrames = 0;
|
||||
this->accumulatedTime = 0;
|
||||
}
|
||||
|
||||
void CFramerateManager::init()
|
||||
@ -591,18 +557,28 @@ void CFramerateManager::framerateDelay()
|
||||
{
|
||||
ui32 currentTicks = SDL_GetTicks();
|
||||
timeElapsed = currentTicks - lastticks;
|
||||
|
||||
|
||||
// FPS is higher than it should be, then wait some time
|
||||
if (timeElapsed < rateticks)
|
||||
{
|
||||
SDL_Delay(ceil(this->rateticks) - timeElapsed);
|
||||
}
|
||||
|
||||
accumulatedTime += timeElapsed;
|
||||
accumulatedFrames++;
|
||||
|
||||
if(accumulatedFrames >= 100)
|
||||
{
|
||||
//about 2 second should be passed
|
||||
fps = ceil(1000.0 / (accumulatedTime/accumulatedFrames));
|
||||
accumulatedTime = 0;
|
||||
accumulatedFrames = 0;
|
||||
};
|
||||
|
||||
currentTicks = SDL_GetTicks();
|
||||
|
||||
fps = ceil(1000.0 / timeElapsed);
|
||||
|
||||
// recalculate timeElapsed for external calls via getElapsed()
|
||||
// limit it to 1000 ms to avoid breaking animation in case of huge lag (e.g. triggered breakpoint)
|
||||
timeElapsed = std::min<ui32>(currentTicks - lastticks, 1000);
|
||||
|
||||
lastticks = SDL_GetTicks();
|
||||
}
|
||||
|
@ -8,9 +8,9 @@ class CFramerateManager;
|
||||
class CGStatusBar;
|
||||
class CIntObject;
|
||||
class IUpdateable;
|
||||
class ILockedUpdatable;
|
||||
class IShowActivatable;
|
||||
class IShowable;
|
||||
template <typename T> struct CondSh;
|
||||
|
||||
/*
|
||||
* CGuiHandler.h, part of VCMI engine
|
||||
@ -29,7 +29,7 @@ private:
|
||||
double rateticks;
|
||||
ui32 lastticks, timeElapsed;
|
||||
int rate;
|
||||
|
||||
ui32 accumulatedTime,accumulatedFrames;
|
||||
public:
|
||||
int fps; // the actual fps value
|
||||
|
||||
@ -58,10 +58,9 @@ private:
|
||||
motioninterested,
|
||||
timeinterested,
|
||||
wheelInterested,
|
||||
doubleClickInterested;
|
||||
#ifndef VCMI_SDL1
|
||||
CIntObjectList textInterested;
|
||||
#endif // VCMI_SDL1
|
||||
doubleClickInterested,
|
||||
textInterested;
|
||||
|
||||
|
||||
void processLists(const ui16 activityFlag, std::function<void (std::list<CIntObject*> *)> cb);
|
||||
public:
|
||||
@ -73,7 +72,7 @@ public:
|
||||
std::vector<IShowable*> objsToBlit;
|
||||
|
||||
SDL_Event * current; //current event - can be set to nullptr to stop handling event
|
||||
ILockedUpdatable *curInt;
|
||||
IUpdateable *curInt;
|
||||
|
||||
Point lastClick;
|
||||
unsigned lastClickTime;
|
||||
@ -104,12 +103,14 @@ public:
|
||||
ui8 captureChildren; //all newly created objects will get their parents from stack and will be added to parents children list
|
||||
std::list<CIntObject *> createdObj; //stack of objs being created
|
||||
|
||||
static SDLKey arrowToNum(SDLKey key); //converts arrow key to according numpad key
|
||||
static SDLKey numToDigit(SDLKey key);//converts numpad digit key to normal digit key
|
||||
static bool isNumKey(SDLKey key, bool number = true); //checks if key is on numpad (numbers - check only for numpad digits)
|
||||
static bool isArrowKey(SDLKey key);
|
||||
static SDL_Keycode arrowToNum(SDL_Keycode key); //converts arrow key to according numpad key
|
||||
static SDL_Keycode numToDigit(SDL_Keycode key);//converts numpad digit key to normal digit key
|
||||
static bool isNumKey(SDL_Keycode key, bool number = true); //checks if key is on numpad (numbers - check only for numpad digits)
|
||||
static bool isArrowKey(SDL_Keycode key);
|
||||
static bool amIGuiThread();
|
||||
static void pushSDLEvent(int type, int usercode = 0);
|
||||
|
||||
static CondSh<bool> terminate_cond; // confirm termination
|
||||
};
|
||||
|
||||
extern CGuiHandler GH; //global gui handler
|
||||
|
@ -15,8 +15,8 @@
|
||||
#include "../Graphics.h"
|
||||
|
||||
struct SDL_Surface;
|
||||
class CPicture;
|
||||
class CGuiHandler;
|
||||
class CPicture;
|
||||
|
||||
struct SDL_KeyboardEvent;
|
||||
|
||||
@ -38,13 +38,6 @@ public:
|
||||
virtual ~IUpdateable(){}; //d-tor
|
||||
};
|
||||
|
||||
class ILockedUpdatable: public IUpdateable
|
||||
{
|
||||
public:
|
||||
virtual void runLocked(std::function<void()> cb) = 0;
|
||||
virtual ~ILockedUpdatable(){}; //d-tor
|
||||
};
|
||||
|
||||
// Defines a show method
|
||||
class IShowable
|
||||
{
|
||||
@ -97,11 +90,6 @@ public:
|
||||
*/
|
||||
std::vector<CIntObject *> children;
|
||||
|
||||
//FIXME: workaround
|
||||
void deactivateKeyboard()
|
||||
{
|
||||
deactivate(KEYBOARD);
|
||||
}
|
||||
|
||||
/*
|
||||
* Public interface
|
||||
@ -133,10 +121,8 @@ public:
|
||||
virtual void keyPressed(const SDL_KeyboardEvent & key){}
|
||||
virtual bool captureThisEvent(const SDL_KeyboardEvent & key); //allows refining captureAllKeys against specific events (eg. don't capture ENTER)
|
||||
|
||||
#ifndef VCMI_SDL1
|
||||
virtual void textInputed(const SDL_TextInputEvent & event){};
|
||||
virtual void textEdited(const SDL_TextEditingEvent & event){};
|
||||
#endif // VCMI_SDL1
|
||||
|
||||
//mouse movement handling
|
||||
bool strongInterest; //if true - report all mouse movements, if not - only when hovered
|
||||
@ -166,15 +152,15 @@ public:
|
||||
|
||||
// activate or deactivate object. Inactive object won't receive any input events (keyboard\mouse)
|
||||
// usually used automatically by parent
|
||||
void activate();
|
||||
void deactivate();
|
||||
void activate() override;
|
||||
void deactivate() override;
|
||||
|
||||
//called each frame to update screen
|
||||
void show(SDL_Surface * to);
|
||||
void show(SDL_Surface * to) override;
|
||||
//called on complete redraw only
|
||||
void showAll(SDL_Surface * to);
|
||||
void showAll(SDL_Surface * to) override;
|
||||
//request complete redraw of this object
|
||||
void redraw();
|
||||
void redraw() override;
|
||||
|
||||
enum EAlignment {TOPLEFT, CENTER, BOTTOMRIGHT};
|
||||
|
||||
@ -221,5 +207,5 @@ public:
|
||||
CKeyShortcut();
|
||||
CKeyShortcut(int key);
|
||||
CKeyShortcut(std::set<int> Keys);
|
||||
virtual void keyPressed(const SDL_KeyboardEvent & key); //call-in
|
||||
virtual void keyPressed(const SDL_KeyboardEvent & key) override; //call-in
|
||||
};
|
||||
|
@ -13,13 +13,6 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef max
|
||||
#undef max
|
||||
#endif
|
||||
#ifdef min
|
||||
#undef min
|
||||
#endif
|
||||
|
||||
struct SDL_MouseMotionEvent;
|
||||
|
||||
// A point with x/y coordinate, used mostly for graphic rendering
|
||||
|
@ -13,23 +13,12 @@
|
||||
#include <SDL_version.h>
|
||||
|
||||
#if (SDL_MAJOR_VERSION == 2)
|
||||
#define VCMI_SDL2
|
||||
|
||||
#include <SDL_keycode.h>
|
||||
typedef int SDLX_Coord;
|
||||
typedef int SDLX_Size;
|
||||
|
||||
typedef SDL_Keycode SDLKey;
|
||||
|
||||
#define SDL_SRCCOLORKEY SDL_TRUE
|
||||
|
||||
#define SDL_FULLSCREEN SDL_WINDOW_FULLSCREEN
|
||||
|
||||
#elif (SDL_MAJOR_VERSION == 1)
|
||||
#define VCMI_SDL1
|
||||
//SDL 1.x
|
||||
typedef Sint16 SDLX_Coord;
|
||||
typedef Uint16 SDLX_Size;
|
||||
#else
|
||||
#error "unknown or unsupported SDL version"
|
||||
#endif
|
||||
|
@ -4,7 +4,6 @@
|
||||
|
||||
#include "../CGameInfo.h"
|
||||
#include "../CMessage.h"
|
||||
#include "../CDefHandler.h"
|
||||
#include "../Graphics.h"
|
||||
#include "../CMT.h"
|
||||
|
||||
@ -14,7 +13,6 @@ const SDL_Color Colors::METALLIC_GOLD = { 173, 142, 66, 0 };
|
||||
const SDL_Color Colors::GREEN = { 0, 255, 0, 0 };
|
||||
const SDL_Color Colors::DEFAULT_KEY_COLOR = {0, 255, 255, 0};
|
||||
|
||||
#if (SDL_MAJOR_VERSION == 2)
|
||||
void SDL_UpdateRect(SDL_Surface *surface, int x, int y, int w, int h)
|
||||
{
|
||||
Rect rect(x,y,w,h);
|
||||
@ -24,10 +22,9 @@ void SDL_UpdateRect(SDL_Surface *surface, int x, int y, int w, int h)
|
||||
SDL_RenderClear(mainRenderer);
|
||||
if(0 != SDL_RenderCopy(mainRenderer, screenTexture, NULL, NULL))
|
||||
logGlobal->errorStream() << __FUNCTION__ << "SDL_RenderCopy " << SDL_GetError();
|
||||
SDL_RenderPresent(mainRenderer);
|
||||
|
||||
SDL_RenderPresent(mainRenderer);
|
||||
|
||||
}
|
||||
#endif // VCMI_SDL1
|
||||
|
||||
SDL_Surface * CSDL_Ext::newSurface(int w, int h, SDL_Surface * mod) //creates new surface, with flags/format same as in surface given
|
||||
{
|
||||
@ -171,7 +168,7 @@ void CSDL_Ext::alphaTransform(SDL_Surface *src)
|
||||
SDL_Color & palColor = src->format->palette->colors[i];
|
||||
palColor = colors[i];
|
||||
}
|
||||
SDL_SetColorKey(src, SDL_SRCCOLORKEY, 0);
|
||||
SDL_SetColorKey(src, SDL_TRUE, 0);
|
||||
}
|
||||
|
||||
static void prepareOutRect(SDL_Rect *src, SDL_Rect *dst, const SDL_Rect & clip_rect)
|
||||
@ -460,11 +457,7 @@ int CSDL_Ext::blit8bppAlphaTo24bppT(const SDL_Surface * src, const SDL_Rect * sr
|
||||
for(int x = w; x; x--)
|
||||
{
|
||||
const SDL_Color &tbc = colors[*color++]; //color to blit
|
||||
#ifdef VCMI_SDL1
|
||||
ColorPutter<bpp, +1>::PutColorAlphaSwitch(p, tbc.r, tbc.g, tbc.b, tbc.unused);
|
||||
#else
|
||||
ColorPutter<bpp, +1>::PutColorAlphaSwitch(p, tbc.r, tbc.g, tbc.b, tbc.a);
|
||||
#endif // 0
|
||||
}
|
||||
}
|
||||
SDL_UnlockSurface(dst);
|
||||
@ -481,7 +474,7 @@ int CSDL_Ext::blit8bppAlphaTo24bpp(const SDL_Surface * src, const SDL_Rect * src
|
||||
case 3: return blit8bppAlphaTo24bppT<3>(src, srcRect, dst, dstRect);
|
||||
case 4: return blit8bppAlphaTo24bppT<4>(src, srcRect, dst, dstRect);
|
||||
default:
|
||||
logGlobal->errorStream() << (int)dst->format->BitsPerPixel << " bpp is not supported!!!";
|
||||
logGlobal->errorStream() << (int)dst->format->BitsPerPixel << " bpp is not supported!!!";
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@ -489,11 +482,7 @@ int CSDL_Ext::blit8bppAlphaTo24bpp(const SDL_Surface * src, const SDL_Rect * src
|
||||
Uint32 CSDL_Ext::colorToUint32(const SDL_Color * color)
|
||||
{
|
||||
Uint32 ret = 0;
|
||||
#ifdef VCMI_SDL1
|
||||
ret+=color->unused;
|
||||
#else
|
||||
ret+=color->a;
|
||||
#endif // 0
|
||||
ret<<=8; //*=256
|
||||
ret+=color->b;
|
||||
ret<<=8; //*=256
|
||||
@ -505,15 +494,10 @@ Uint32 CSDL_Ext::colorToUint32(const SDL_Color * color)
|
||||
|
||||
void CSDL_Ext::update(SDL_Surface * what)
|
||||
{
|
||||
#ifdef VCMI_SDL1
|
||||
if(what)
|
||||
SDL_UpdateRect(what, 0, 0, what->w, what->h);
|
||||
#else
|
||||
if(!what)
|
||||
return;
|
||||
if(0 !=SDL_UpdateTexture(screenTexture, nullptr, what->pixels, what->pitch))
|
||||
logGlobal->errorStream() << __FUNCTION__ << "SDL_UpdateTexture " << SDL_GetError();
|
||||
#endif // VCMI_SDL1
|
||||
logGlobal->errorStream() << __FUNCTION__ << "SDL_UpdateTexture " << SDL_GetError();
|
||||
}
|
||||
void CSDL_Ext::drawBorder(SDL_Surface * sur, int x, int y, int w, int h, const int3 &color)
|
||||
{
|
||||
@ -571,7 +555,7 @@ void CSDL_Ext::setPlayerColor(SDL_Surface * sur, PlayerColor player)
|
||||
SDL_SetColors(sur, color, 5, 1);
|
||||
}
|
||||
else
|
||||
logGlobal->warnStream() << "Warning, setPlayerColor called on not 8bpp surface!";
|
||||
logGlobal->warnStream() << "Warning, setPlayerColor called on not 8bpp surface!";
|
||||
}
|
||||
|
||||
TColorPutter CSDL_Ext::getPutterFor(SDL_Surface * const &dest, int incrementing)
|
||||
@ -592,7 +576,7 @@ case BytesPerPixel: \
|
||||
CASE_BPP(3)
|
||||
CASE_BPP(4)
|
||||
default:
|
||||
logGlobal->errorStream() << (int)dest->format->BitsPerPixel << "bpp is not supported!";
|
||||
logGlobal->errorStream() << (int)dest->format->BitsPerPixel << "bpp is not supported!";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@ -606,7 +590,7 @@ TColorPutterAlpha CSDL_Ext::getPutterAlphaFor(SDL_Surface * const &dest, int inc
|
||||
CASE_BPP(3)
|
||||
CASE_BPP(4)
|
||||
default:
|
||||
logGlobal->errorStream() << (int)dest->format->BitsPerPixel << "bpp is not supported!";
|
||||
logGlobal->errorStream() << (int)dest->format->BitsPerPixel << "bpp is not supported!";
|
||||
return nullptr;
|
||||
}
|
||||
#undef CASE_BPP
|
||||
@ -632,22 +616,14 @@ bool CSDL_Ext::isTransparent( SDL_Surface * srf, int x, int y )
|
||||
return true;
|
||||
|
||||
SDL_Color color;
|
||||
|
||||
#ifdef VCMI_SDL1
|
||||
SDL_GetRGBA(SDL_GetPixel(srf, x, y), srf->format, &color.r, &color.g, &color.b, &color.unused);
|
||||
#else
|
||||
|
||||
SDL_GetRGBA(SDL_GetPixel(srf, x, y), srf->format, &color.r, &color.g, &color.b, &color.a);
|
||||
#endif // 0
|
||||
|
||||
// color is considered transparent here if
|
||||
// a) image has aplha: less than 50% transparency
|
||||
// b) no alpha: color is cyan
|
||||
if (srf->format->Amask)
|
||||
#ifdef VCMI_SDL1
|
||||
return color.unused < 128; // almost transparent
|
||||
#else
|
||||
return color.a < 128; // almost transparent
|
||||
#endif // 0
|
||||
else
|
||||
return (color.r == 0 && color.g == 255 && color.b == 255);
|
||||
}
|
||||
@ -698,7 +674,7 @@ BlitterWithRotationVal CSDL_Ext::getBlitterWithRotation(SDL_Surface *dest)
|
||||
case 3: return blitWithRotateClipVal<3>;
|
||||
case 4: return blitWithRotateClipVal<4>;
|
||||
default:
|
||||
logGlobal->errorStream() << (int)dest->format->BitsPerPixel << " bpp is not supported!!!";
|
||||
logGlobal->errorStream() << (int)dest->format->BitsPerPixel << " bpp is not supported!!!";
|
||||
break;
|
||||
}
|
||||
|
||||
@ -714,7 +690,7 @@ BlitterWithRotationVal CSDL_Ext::getBlitterWithRotationAndAlpha(SDL_Surface *des
|
||||
case 3: return blitWithRotateClipValWithAlpha<3>;
|
||||
case 4: return blitWithRotateClipValWithAlpha<4>;
|
||||
default:
|
||||
logGlobal->errorStream() << (int)dest->format->BitsPerPixel << " bpp is not supported!!!";
|
||||
logGlobal->errorStream() << (int)dest->format->BitsPerPixel << " bpp is not supported!!!";
|
||||
break;
|
||||
}
|
||||
|
||||
@ -988,42 +964,34 @@ SDL_Color CSDL_Ext::makeColor(ui8 r, ui8 g, ui8 b, ui8 a)
|
||||
|
||||
void CSDL_Ext::startTextInput(SDL_Rect * where)
|
||||
{
|
||||
#ifndef VCMI_SDL1
|
||||
if (SDL_IsTextInputActive() == SDL_FALSE)
|
||||
{
|
||||
SDL_StartTextInput();
|
||||
}
|
||||
if (SDL_IsTextInputActive() == SDL_FALSE)
|
||||
{
|
||||
SDL_StartTextInput();
|
||||
}
|
||||
SDL_SetTextInputRect(where);
|
||||
#endif
|
||||
}
|
||||
|
||||
void CSDL_Ext::stopTextInput()
|
||||
{
|
||||
#ifndef VCMI_SDL1
|
||||
if (SDL_IsTextInputActive() == SDL_TRUE)
|
||||
{
|
||||
SDL_StopTextInput();
|
||||
}
|
||||
#endif
|
||||
{
|
||||
SDL_StopTextInput();
|
||||
}
|
||||
}
|
||||
|
||||
STRONG_INLINE static uint32_t mapColor(SDL_Surface * surface, SDL_Color color)
|
||||
{
|
||||
#ifdef VCMI_SDL1
|
||||
return SDL_MapRGB(surface->format, color.r, color.g, color.b);
|
||||
#else
|
||||
return SDL_MapRGBA(surface->format, color.r, color.g, color.b, color.a);
|
||||
#endif
|
||||
return SDL_MapRGBA(surface->format, color.r, color.g, color.b, color.a);
|
||||
}
|
||||
|
||||
void CSDL_Ext::setColorKey(SDL_Surface * surface, SDL_Color color)
|
||||
{
|
||||
uint32_t key = mapColor(surface,color);
|
||||
SDL_SetColorKey(surface, SDL_SRCCOLORKEY, key);
|
||||
SDL_SetColorKey(surface, SDL_TRUE, key);
|
||||
}
|
||||
|
||||
void CSDL_Ext::setDefaultColorKey(SDL_Surface * surface)
|
||||
{
|
||||
{
|
||||
setColorKey(surface, Colors::DEFAULT_KEY_COLOR);
|
||||
}
|
||||
|
||||
@ -1034,7 +1002,7 @@ void CSDL_Ext::setDefaultColorKeyPresize(SDL_Surface * surface)
|
||||
|
||||
// set color key only if exactly such color was found
|
||||
if (color.r == Colors::DEFAULT_KEY_COLOR.r && color.g == Colors::DEFAULT_KEY_COLOR.g && color.b == Colors::DEFAULT_KEY_COLOR.b)
|
||||
SDL_SetColorKey(surface, SDL_SRCCOLORKEY, key);
|
||||
SDL_SetColorKey(surface, SDL_TRUE, key);
|
||||
}
|
||||
|
||||
|
||||
|
@ -10,35 +10,14 @@
|
||||
|
||||
#pragma once
|
||||
#include <SDL_version.h>
|
||||
|
||||
#ifndef VCMI_SDL1
|
||||
#include <SDL_render.h>
|
||||
#endif
|
||||
|
||||
#include <SDL_video.h>
|
||||
#include <SDL_events.h>
|
||||
#include "../../lib/int3.h"
|
||||
//#include "../Graphics.h"
|
||||
#include "Geometries.h"
|
||||
#include "../../lib/GameConstants.h"
|
||||
|
||||
|
||||
//A macro to force inlining some of our functions. Compiler (at least MSVC) is not so smart here-> without that displaying is MUCH slower
|
||||
#ifdef _MSC_VER
|
||||
#define STRONG_INLINE __forceinline
|
||||
#elif __GNUC__
|
||||
#define STRONG_INLINE inline __attribute__((always_inline))
|
||||
#else
|
||||
#define STRONG_INLINE inline
|
||||
#endif
|
||||
|
||||
#if SDL_VERSION_ATLEAST(1,3,0)
|
||||
#define SDL_GetKeyState SDL_GetKeyboardState
|
||||
#endif
|
||||
|
||||
//SDL2 support
|
||||
#if (SDL_MAJOR_VERSION == 2)
|
||||
|
||||
extern SDL_Window * mainWindow;
|
||||
extern SDL_Renderer * mainRenderer;
|
||||
extern SDL_Texture * screenTexture;
|
||||
@ -54,64 +33,35 @@ inline void SDL_WarpMouse(int x, int y)
|
||||
}
|
||||
|
||||
void SDL_UpdateRect(SDL_Surface *surface, int x, int y, int w, int h);
|
||||
#endif
|
||||
|
||||
inline bool isCtrlKeyDown()
|
||||
{
|
||||
#ifdef VCMI_SDL1
|
||||
return SDL_GetKeyState(nullptr)[SDLK_LCTRL] || SDL_GetKeyState(nullptr)[SDLK_RCTRL];
|
||||
#else
|
||||
return SDL_GetKeyboardState(nullptr)[SDL_SCANCODE_LCTRL] || SDL_GetKeyboardState(nullptr)[SDL_SCANCODE_RCTRL];
|
||||
#endif
|
||||
}
|
||||
|
||||
inline bool isAltKeyDown()
|
||||
{
|
||||
#ifdef VCMI_SDL1
|
||||
return SDL_GetKeyState(nullptr)[SDLK_LALT] || SDL_GetKeyState(nullptr)[SDLK_RALT];
|
||||
#else
|
||||
return SDL_GetKeyboardState(nullptr)[SDL_SCANCODE_LALT] || SDL_GetKeyboardState(nullptr)[SDL_SCANCODE_RALT];
|
||||
#endif
|
||||
}
|
||||
|
||||
inline bool isShiftKeyDown()
|
||||
{
|
||||
#ifdef VCMI_SDL1
|
||||
return SDL_GetKeyState(nullptr)[SDLK_LSHIFT] || SDL_GetKeyState(nullptr)[SDLK_RSHIFT];
|
||||
#else
|
||||
return SDL_GetKeyboardState(nullptr)[SDL_SCANCODE_LSHIFT] || SDL_GetKeyboardState(nullptr)[SDL_SCANCODE_RSHIFT];
|
||||
#endif
|
||||
}
|
||||
namespace CSDL_Ext
|
||||
{
|
||||
STRONG_INLINE void colorSetAlpha(SDL_Color & color, Uint8 alpha)
|
||||
{
|
||||
#ifdef VCMI_SDL1
|
||||
color.unused = alpha;
|
||||
#else
|
||||
color.a = alpha;
|
||||
#endif
|
||||
}
|
||||
//todo: should this better be assignment operator?
|
||||
STRONG_INLINE void colorAssign(SDL_Color & dest, const SDL_Color & source)
|
||||
{
|
||||
dest.r = source.r;
|
||||
dest.g = source.g;
|
||||
dest.b = source.b;
|
||||
#ifdef VCMI_SDL1
|
||||
dest.unused = source.unused;
|
||||
#else
|
||||
dest.a = source.a;
|
||||
#endif
|
||||
}
|
||||
|
||||
inline void setAlpha(SDL_Surface * bg, int value)
|
||||
{
|
||||
#ifdef VCMI_SDL1
|
||||
SDL_SetAlpha(bg, SDL_SRCALPHA, value);
|
||||
#else
|
||||
SDL_SetSurfaceAlphaMod(bg, value);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
struct Rect;
|
||||
@ -154,7 +104,7 @@ template<typename IntType>
|
||||
std::string makeNumberShort(IntType number, IntType maxLength = 3) //the output is a string containing at most 5 characters [4 if positive] (eg. intead 10000 it gives 10k)
|
||||
{
|
||||
IntType max = pow(10, maxLength);
|
||||
if (abs(number) < max)
|
||||
if (std::abs(number) < max)
|
||||
return boost::lexical_cast<std::string>(number);
|
||||
|
||||
std::string symbols = " kMGTPE";
|
||||
|
@ -135,11 +135,7 @@ struct ColorPutter<2, incrementPtr>
|
||||
template<int bpp, int incrementPtr>
|
||||
STRONG_INLINE void ColorPutter<bpp, incrementPtr>::PutColorAlpha(Uint8 *&ptr, const SDL_Color & Color)
|
||||
{
|
||||
#ifdef VCMI_SDL1
|
||||
PutColor(ptr, Color.r, Color.g, Color.b, Color.unused);
|
||||
#else
|
||||
PutColor(ptr, Color.r, Color.g, Color.b, Color.a);
|
||||
#endif
|
||||
}
|
||||
|
||||
template<int bpp, int incrementPtr>
|
||||
@ -268,11 +264,7 @@ STRONG_INLINE void ColorPutter<2, incrementPtr>::PutColor(Uint8 *&ptr, const Uin
|
||||
template <int incrementPtr>
|
||||
STRONG_INLINE void ColorPutter<2, incrementPtr>::PutColorAlpha(Uint8 *&ptr, const SDL_Color & Color)
|
||||
{
|
||||
#ifdef VCMI_SDL1
|
||||
PutColor(ptr, Color.r, Color.g, Color.b, Color.unused);
|
||||
#else
|
||||
PutColor(ptr, Color.r, Color.g, Color.b, Color.a);
|
||||
#endif
|
||||
}
|
||||
|
||||
template <int incrementPtr>
|
||||
|
@ -528,7 +528,7 @@ CMapHandler::CMapNormalBlitter::CMapNormalBlitter(CMapHandler * parent)
|
||||
defaultTileRect = Rect(0, 0, tileSize, tileSize);
|
||||
}
|
||||
|
||||
SDL_Surface * CMapHandler::CMapWorldViewBlitter::objectToIcon(Obj id, si32 subId, PlayerColor owner) const
|
||||
IImage * CMapHandler::CMapWorldViewBlitter::objectToIcon(Obj id, si32 subId, PlayerColor owner) const
|
||||
{
|
||||
int ownerIndex = 0;
|
||||
if(owner < PlayerColor::PLAYER_LIMIT)
|
||||
@ -539,27 +539,27 @@ SDL_Surface * CMapHandler::CMapWorldViewBlitter::objectToIcon(Obj id, si32 subId
|
||||
{
|
||||
ownerIndex = PlayerColor::PLAYER_LIMIT.getNum() * 19;
|
||||
}
|
||||
|
||||
|
||||
switch(id)
|
||||
{
|
||||
case Obj::MONOLITH_ONE_WAY_ENTRANCE:
|
||||
case Obj::MONOLITH_ONE_WAY_EXIT:
|
||||
case Obj::MONOLITH_TWO_WAY:
|
||||
return info->iconsDef->ourImages[(int)EWorldViewIcon::TELEPORT].bitmap;
|
||||
return info->icons->getImage((int)EWorldViewIcon::TELEPORT);
|
||||
case Obj::SUBTERRANEAN_GATE:
|
||||
return info->iconsDef->ourImages[(int)EWorldViewIcon::GATE].bitmap;
|
||||
return info->icons->getImage((int)EWorldViewIcon::GATE);
|
||||
case Obj::ARTIFACT:
|
||||
return info->iconsDef->ourImages[(int)EWorldViewIcon::ARTIFACT].bitmap;
|
||||
return info->icons->getImage((int)EWorldViewIcon::ARTIFACT);
|
||||
case Obj::TOWN:
|
||||
return info->iconsDef->ourImages[(int)EWorldViewIcon::TOWN + ownerIndex].bitmap;
|
||||
return info->icons->getImage((int)EWorldViewIcon::TOWN + ownerIndex);
|
||||
case Obj::HERO:
|
||||
return info->iconsDef->ourImages[(int)EWorldViewIcon::HERO + ownerIndex].bitmap;
|
||||
return info->icons->getImage((int)EWorldViewIcon::HERO + ownerIndex);
|
||||
case Obj::MINE:
|
||||
return info->iconsDef->ourImages[(int)EWorldViewIcon::MINE_WOOD + subId + ownerIndex].bitmap;
|
||||
return info->icons->getImage((int)EWorldViewIcon::MINE_WOOD + subId + ownerIndex);
|
||||
case Obj::RESOURCE:
|
||||
return info->iconsDef->ourImages[(int)EWorldViewIcon::RES_WOOD + subId + ownerIndex].bitmap;
|
||||
}
|
||||
return nullptr;
|
||||
return info->icons->getImage((int)EWorldViewIcon::RES_WOOD + subId + ownerIndex);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void CMapHandler::CMapWorldViewBlitter::calculateWorldViewCameraPos()
|
||||
@ -645,13 +645,13 @@ void CMapHandler::CMapWorldViewBlitter::drawTileOverlay(SDL_Surface * targetSurf
|
||||
{
|
||||
auto drawIcon = [this,targetSurf](Obj id, si32 subId, PlayerColor owner)
|
||||
{
|
||||
SDL_Surface * wvIcon = this->objectToIcon(id, subId, owner);
|
||||
IImage * wvIcon = this->objectToIcon(id, subId, owner);
|
||||
|
||||
if (nullptr != wvIcon)
|
||||
if(nullptr != wvIcon)
|
||||
{
|
||||
// centering icon on the object
|
||||
Rect destRect(realPos.x + tileSize / 2 - wvIcon->w / 2, realPos.y + tileSize / 2 - wvIcon->h / 2, wvIcon->w, wvIcon->h);
|
||||
CSDL_Ext::blitSurface(wvIcon, nullptr, targetSurf, &destRect);
|
||||
Point dest(realPos.x + tileSize / 2 - wvIcon->width() / 2, realPos.y + tileSize / 2 - wvIcon->height() / 2);
|
||||
wvIcon->draw(targetSurf, dest.x, dest.y);
|
||||
}
|
||||
};
|
||||
|
||||
@ -660,7 +660,7 @@ void CMapHandler::CMapWorldViewBlitter::drawTileOverlay(SDL_Surface * targetSurf
|
||||
{
|
||||
const CGObjectInstance * obj = object.obj;
|
||||
|
||||
const bool sameLevel = obj->pos.z == pos.z;
|
||||
const bool sameLevel = obj->pos.z == pos.z;
|
||||
const bool isVisible = (*info->visibilityMap)[pos.x][pos.y][pos.z];
|
||||
const bool isVisitable = obj->visitableAt(pos.x, pos.y);
|
||||
|
||||
@ -673,31 +673,31 @@ void CMapHandler::CMapWorldViewBlitter::drawOverlayEx(SDL_Surface * targetSurf)
|
||||
{
|
||||
if(nullptr == info->additionalIcons)
|
||||
return;
|
||||
|
||||
|
||||
const int3 bottomRight = pos + tileCount;
|
||||
|
||||
|
||||
for(const ObjectPosInfo & iconInfo : *(info->additionalIcons))
|
||||
{
|
||||
if( iconInfo.pos.z != pos.z)
|
||||
continue;
|
||||
|
||||
|
||||
if((iconInfo.pos.x < topTile.x) || (iconInfo.pos.y < topTile.y))
|
||||
continue;
|
||||
|
||||
|
||||
if((iconInfo.pos.x > bottomRight.x) || (iconInfo.pos.y > bottomRight.y))
|
||||
continue;
|
||||
|
||||
continue;
|
||||
|
||||
realPos.x = initPos.x + (iconInfo.pos.x - topTile.x) * tileSize;
|
||||
realPos.y = initPos.x + (iconInfo.pos.y - topTile.y) * tileSize;
|
||||
|
||||
SDL_Surface * wvIcon = this->objectToIcon(iconInfo.id, iconInfo.subId, iconInfo.owner);
|
||||
|
||||
if (nullptr != wvIcon)
|
||||
|
||||
IImage * wvIcon = this->objectToIcon(iconInfo.id, iconInfo.subId, iconInfo.owner);
|
||||
|
||||
if(nullptr != wvIcon)
|
||||
{
|
||||
// centering icon on the object
|
||||
Rect destRect(realPos.x + tileSize / 2 - wvIcon->w / 2, realPos.y + tileSize / 2 - wvIcon->h / 2, wvIcon->w, wvIcon->h);
|
||||
CSDL_Ext::blitSurface(wvIcon, nullptr, targetSurf, &destRect);
|
||||
}
|
||||
Point dest(realPos.x + tileSize / 2 - wvIcon->width() / 2, realPos.y + tileSize / 2 - wvIcon->height() / 2);
|
||||
wvIcon->draw(targetSurf, dest.x, dest.y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -778,8 +778,8 @@ void CMapHandler::CMapPuzzleViewBlitter::drawObjects(SDL_Surface * targetSurf, c
|
||||
// grail X mark
|
||||
if(pos.x == info->grailPos.x && pos.y == info->grailPos.y)
|
||||
{
|
||||
Rect destRect(realTileRect);
|
||||
CSDL_Ext::blit8bppAlphaTo24bpp(graphics->heroMoveArrows->ourImages[0].bitmap, nullptr, targetSurf, &destRect);
|
||||
const IImage * mark = graphics->heroMoveArrows->getImage(0);
|
||||
mark->draw(targetSurf,realTileRect.x,realTileRect.y);
|
||||
}
|
||||
}
|
||||
|
||||
@ -837,7 +837,7 @@ void CMapHandler::CMapBlitter::drawObjects(SDL_Surface * targetSurf, const Terra
|
||||
for(auto & object : objects)
|
||||
{
|
||||
if (object.fadeAnimKey >= 0)
|
||||
{
|
||||
{
|
||||
auto fadeIter = parent->fadeAnims.find(object.fadeAnimKey);
|
||||
if (fadeIter != parent->fadeAnims.end())
|
||||
{
|
||||
@ -850,27 +850,34 @@ void CMapHandler::CMapBlitter::drawObjects(SDL_Surface * targetSurf, const Terra
|
||||
logGlobal->errorStream() << "Fading map object with missing fade anim : " << object.fadeAnimKey;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
const CGObjectInstance * obj = object.obj;
|
||||
if (!obj)
|
||||
{
|
||||
logGlobal->errorStream() << "Stray map object that isn't fading";
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
if (!graphics->getDef(obj))
|
||||
processDef(obj->appearance);
|
||||
if (!graphics->getDef(obj) && !obj->appearance.animationFile.empty())
|
||||
logGlobal->errorStream() << "Failed to load image " << obj->appearance.animationFile;
|
||||
if (!graphics->getDef(obj))
|
||||
{
|
||||
if (!obj->appearance.animationFile.empty())
|
||||
logGlobal->errorStream() << "Failed to load image " << obj->appearance.animationFile;
|
||||
else
|
||||
logGlobal->warnStream() << boost::format("Def name for obj %d (%d,%d) is empty!") % obj->id % obj->ID % obj->subID;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!canDrawObject(obj))
|
||||
continue;
|
||||
|
||||
|
||||
auto objData = findObjectBitmap(obj, info->anim);
|
||||
if (objData.objBitmap)
|
||||
{
|
||||
{
|
||||
Rect srcRect(object.rect.x, object.rect.y, tileSize, tileSize);
|
||||
|
||||
|
||||
drawObject(targetSurf, objData.objBitmap, &srcRect, objData.isMoving);
|
||||
if (objData.flagBitmap)
|
||||
{
|
||||
@ -883,7 +890,7 @@ void CMapHandler::CMapBlitter::drawObjects(SDL_Surface * targetSurf, const Terra
|
||||
else if (obj->pos.x == pos.x && obj->pos.y == pos.y)
|
||||
{
|
||||
Rect dstRect(realPos.x - 2 * tileSize, realPos.y - tileSize, 3 * tileSize, 2 * tileSize);
|
||||
drawHeroFlag(targetSurf, objData.flagBitmap, nullptr, &dstRect, false);
|
||||
drawHeroFlag(targetSurf, objData.flagBitmap, nullptr, &dstRect, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -939,7 +946,7 @@ void CMapHandler::CMapBlitter::blit(SDL_Surface * targetSurf, const MapDrawingIn
|
||||
{
|
||||
if (pos.y < 0 || pos.y >= parent->sizes.y)
|
||||
continue;
|
||||
|
||||
|
||||
const bool isVisible = canDrawCurrentTile();
|
||||
|
||||
realTileRect.x = realPos.x;
|
||||
@ -948,13 +955,13 @@ void CMapHandler::CMapBlitter::blit(SDL_Surface * targetSurf, const MapDrawingIn
|
||||
const TerrainTile2 & tile = parent->ttiles[pos.x][pos.y][pos.z];
|
||||
const TerrainTile & tinfo = parent->map->getTile(pos);
|
||||
const TerrainTile * tinfoUpper = pos.y > 0 ? &parent->map->getTile(int3(pos.x, pos.y - 1, pos.z)) : nullptr;
|
||||
|
||||
|
||||
if(isVisible || info->showAllTerrain)
|
||||
{
|
||||
drawTileTerrain(targetSurf, tinfo, tile);
|
||||
if (tinfo.riverType)
|
||||
drawRiver(targetSurf, tinfo);
|
||||
drawRoad(targetSurf, tinfo, tinfoUpper);
|
||||
drawRoad(targetSurf, tinfo, tinfoUpper);
|
||||
}
|
||||
|
||||
if(isVisible)
|
||||
@ -1010,8 +1017,8 @@ void CMapHandler::CMapBlitter::blit(SDL_Surface * targetSurf, const MapDrawingIn
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
drawOverlayEx(targetSurf);
|
||||
|
||||
drawOverlayEx(targetSurf);
|
||||
|
||||
// drawDebugGrid()
|
||||
if (settings["session"]["showGrid"].Bool())
|
||||
@ -1084,10 +1091,10 @@ CMapHandler::AnimBitmapHolder CMapHandler::CMapBlitter::findBoatBitmap(const CGB
|
||||
}
|
||||
|
||||
SDL_Surface * CMapHandler::CMapBlitter::findFlagBitmap(const CGHeroInstance * hero, int anim, const PlayerColor * color, int indexOffset) const
|
||||
{
|
||||
{
|
||||
if (!hero)
|
||||
return nullptr;
|
||||
|
||||
|
||||
if (hero->boat)
|
||||
return findBoatFlagBitmap(hero->boat, anim, color, indexOffset, hero->moveDir);
|
||||
return findHeroFlagBitmap(hero, anim, color, indexOffset);
|
||||
@ -1114,8 +1121,8 @@ SDL_Surface * CMapHandler::CMapBlitter::findBoatFlagBitmap(const CGBoat * boat,
|
||||
SDL_Surface * CMapHandler::CMapBlitter::findFlagBitmapInternal(const CDefEssential * def, int anim, int indexOffset, ui8 dir, bool moving) const
|
||||
{
|
||||
if (moving)
|
||||
return def->ourImages[indexOffset + anim % FRAMES_PER_MOVE_ANIM_GROUP].bitmap;
|
||||
return def->ourImages[getHeroFrameNum(dir, false) * FRAMES_PER_MOVE_ANIM_GROUP + (anim / 4) % FRAMES_PER_MOVE_ANIM_GROUP].bitmap;
|
||||
return def->ourImages[indexOffset + anim % FRAMES_PER_MOVE_ANIM_GROUP].bitmap;
|
||||
return def->ourImages[getHeroFrameNum(dir, false) * FRAMES_PER_MOVE_ANIM_GROUP + (anim / 4) % FRAMES_PER_MOVE_ANIM_GROUP].bitmap;
|
||||
}
|
||||
|
||||
int CMapHandler::CMapBlitter::findAnimIndexByGroup(const CDefEssential * def, int groupNum) const
|
||||
@ -1134,9 +1141,9 @@ CMapHandler::AnimBitmapHolder CMapHandler::CMapBlitter::findObjectBitmap(const C
|
||||
return findHeroBitmap(static_cast<const CGHeroInstance*>(obj), anim);
|
||||
if (obj->ID == Obj::BOAT)
|
||||
return findBoatBitmap(static_cast<const CGBoat*>(obj), anim);
|
||||
|
||||
// normal object
|
||||
|
||||
|
||||
// normal object
|
||||
|
||||
const std::vector<Cimage> &ourImages = graphics->getDef(obj)->ourImages;
|
||||
SDL_Surface *bitmap = ourImages[(anim + getPhaseShift(obj)) % ourImages.size()].bitmap;
|
||||
|
||||
@ -1207,14 +1214,14 @@ std::pair<SDL_Surface *, bool> CMapHandler::CMapBlitter::getVisBitmap() const
|
||||
}
|
||||
|
||||
bool CMapHandler::updateObjectsFade()
|
||||
{
|
||||
{
|
||||
for (auto iter = fadeAnims.begin(); iter != fadeAnims.end(); )
|
||||
{
|
||||
int3 pos = (*iter).second.first;
|
||||
CFadeAnimation * anim = (*iter).second.second;
|
||||
|
||||
|
||||
anim->update();
|
||||
|
||||
|
||||
if (anim->isFading())
|
||||
++iter;
|
||||
else // fade finished
|
||||
@ -1223,7 +1230,7 @@ bool CMapHandler::updateObjectsFade()
|
||||
for (auto objIter = objs.begin(); objIter != objs.end(); ++objIter)
|
||||
{
|
||||
if ((*objIter).fadeAnimKey == (*iter).first)
|
||||
{
|
||||
{
|
||||
logAnim->traceStream() << "Fade anim finished for obj at " << pos << "; remaining: " << (fadeAnims.size() - 1);
|
||||
if (anim->fadingMode == CFadeAnimation::EMode::OUT)
|
||||
objs.erase(objIter); // if this was fadeout, remove the object from the map
|
||||
@ -1232,10 +1239,11 @@ bool CMapHandler::updateObjectsFade()
|
||||
break;
|
||||
}
|
||||
}
|
||||
delete (*iter).second.second;
|
||||
iter = fadeAnims.erase(iter);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return !fadeAnims.empty();
|
||||
}
|
||||
|
||||
@ -1243,7 +1251,7 @@ bool CMapHandler::startObjectFade(TerrainTileObject & obj, bool in, int3 pos)
|
||||
{
|
||||
SDL_Surface * fadeBitmap;
|
||||
assert(obj.obj);
|
||||
|
||||
|
||||
auto objData = normalBlitter->findObjectBitmap(obj.obj, 0);
|
||||
if (objData.objBitmap)
|
||||
{
|
||||
@ -1252,7 +1260,7 @@ bool CMapHandler::startObjectFade(TerrainTileObject & obj, bool in, int3 pos)
|
||||
logAnim->debugStream() << "Ignoring fade of moving object";
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
fadeBitmap = CSDL_Ext::newSurface(32, 32); // TODO cache these bitmaps instead of creating new ones?
|
||||
Rect objSrcRect(obj.rect.x, obj.rect.y, 32, 32);
|
||||
CSDL_Ext::blit8bppAlphaTo24bpp(objData.objBitmap, &objSrcRect, fadeBitmap, nullptr);
|
||||
@ -1268,12 +1276,12 @@ bool CMapHandler::startObjectFade(TerrainTileObject & obj, bool in, int3 pos)
|
||||
anim->init(in ? CFadeAnimation::EMode::IN : CFadeAnimation::EMode::OUT, fadeBitmap, true);
|
||||
fadeAnims[++fadeAnimCounter] = std::pair<int3, CFadeAnimation*>(pos, anim);
|
||||
obj.fadeAnimKey = fadeAnimCounter;
|
||||
|
||||
logAnim->traceStream() << "Fade anim started for obj " << obj.obj->ID
|
||||
|
||||
logAnim->traceStream() << "Fade anim started for obj " << obj.obj->ID
|
||||
<< " at " << pos << "; anim count: " << fadeAnims.size();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -1296,17 +1304,17 @@ bool CMapHandler::printObject(const CGObjectInstance *obj, bool fadein /* = fals
|
||||
cr.x = fx*32;
|
||||
cr.y = fy*32;
|
||||
TerrainTileObject toAdd(obj, cr);
|
||||
|
||||
|
||||
if((obj->pos.x + fx - tilesW+1)>=0 && (obj->pos.x + fx - tilesW+1)<ttiles.size()-frameW && (obj->pos.y + fy - tilesH+1)>=0 && (obj->pos.y + fy - tilesH+1)<ttiles[0].size()-frameH)
|
||||
{
|
||||
int3 pos(obj->pos.x + fx - tilesW + 1, obj->pos.y + fy - tilesH + 1, obj->pos.z);
|
||||
TerrainTile2 & curt = ttiles[pos.x][pos.y][pos.z];
|
||||
|
||||
TerrainTile2 & curt = ttiles[pos.x][pos.y][pos.z];
|
||||
|
||||
if (fadein && ADVOPT.objectFading)
|
||||
{
|
||||
startObjectFade(toAdd, true, pos);
|
||||
}
|
||||
|
||||
|
||||
auto i = curt.objects.begin();
|
||||
for(; i != curt.objects.end(); i++)
|
||||
{
|
||||
@ -1322,22 +1330,54 @@ bool CMapHandler::printObject(const CGObjectInstance *obj, bool fadein /* = fals
|
||||
curt.objects.insert(i, toAdd);
|
||||
}
|
||||
|
||||
} // for(int fy=0; fy<tilesH; ++fy)
|
||||
} //for(int fx=0; fx<tilesW; ++fx)
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CMapHandler::hideObject(const CGObjectInstance *obj, bool fadeout /* = false */)
|
||||
{
|
||||
// do we actually need to search through the whole map for this?
|
||||
for (size_t i=0; i<map->width; i++)
|
||||
//optimized version which reveals weird bugs with missing def name
|
||||
//auto pos = obj->pos;
|
||||
|
||||
//for (size_t i = pos.x; i > pos.x - obj->getWidth(); i--)
|
||||
//{
|
||||
// for (size_t j = pos.y; j > pos.y - obj->getHeight(); j--)
|
||||
// {
|
||||
// int3 t(i, j, pos.z);
|
||||
// if (!map->isInTheMap(t))
|
||||
// continue;
|
||||
|
||||
// auto &objs = ttiles[i][j][pos.z].objects;
|
||||
// for (size_t x = 0; x < objs.size(); x++)
|
||||
// {
|
||||
// auto ourObj = objs[x].obj;
|
||||
// if (ourObj && ourObj->id == obj->id)
|
||||
// {
|
||||
// if (fadeout && ADVOPT.objectFading) // object should be faded == erase is delayed until the end of fadeout
|
||||
// {
|
||||
// if (startObjectFade(objs[x], false, t))
|
||||
// objs[x].obj = nullptr; //set original pointer to null
|
||||
// else
|
||||
// objs.erase(objs.begin() + x);
|
||||
// }
|
||||
// else
|
||||
// objs.erase(objs.begin() + x);
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
//}
|
||||
|
||||
for (size_t i = 0; i<map->width; i++)
|
||||
{
|
||||
for (size_t j=0; j<map->height; j++)
|
||||
for (size_t j = 0; j<map->height; j++)
|
||||
{
|
||||
for (size_t k=0; k<(map->twoLevel ? 2 : 1); k++)
|
||||
for (size_t k = 0; k<(map->twoLevel ? 2 : 1); k++)
|
||||
{
|
||||
auto &objs = ttiles[i][j][k].objects;
|
||||
for(size_t x=0; x < objs.size(); x++)
|
||||
for (size_t x = 0; x < objs.size(); x++)
|
||||
{
|
||||
if (objs[x].obj && objs[x].obj->id == obj->id)
|
||||
{
|
||||
@ -1356,6 +1396,7 @@ bool CMapHandler::hideObject(const CGObjectInstance *obj, bool fadeout /* = fals
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
bool CMapHandler::removeObject(CGObjectInstance *obj, bool fadeout /* = false */)
|
||||
@ -1503,7 +1544,7 @@ CMapHandler::~CMapHandler()
|
||||
for(int j=0; j < elem.size(); ++j)
|
||||
SDL_FreeSurface(elem[j]);
|
||||
}
|
||||
|
||||
|
||||
for (auto & elem : fadeAnims)
|
||||
{
|
||||
delete elem.second.second;
|
||||
@ -1536,10 +1577,16 @@ void CMapHandler::getTerrainDescr( const int3 &pos, std::string & out, bool terN
|
||||
}
|
||||
}
|
||||
|
||||
if(t.hasFavourableWinds())
|
||||
if(t.hasFavorableWinds())
|
||||
out = CGI->objtypeh->getObjectName(Obj::FAVORABLE_WINDS);
|
||||
else if(terName)
|
||||
{
|
||||
out = CGI->generaltexth->terrainNames[t.terType];
|
||||
if(t.getDiggingStatus(false) == EDiggingStatus::CAN_DIG)
|
||||
{
|
||||
out = boost::str(boost::format("%s %s") % out % CGI->generaltexth->allTexts[330]); /// digging ok
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CMapHandler::discardWorldViewCache()
|
||||
|
@ -26,6 +26,8 @@ struct TerrainTile;
|
||||
struct SDL_Surface;
|
||||
struct SDL_Rect;
|
||||
class CDefEssential;
|
||||
class CAnimation;
|
||||
class IImage;
|
||||
class CFadeAnimation;
|
||||
class PlayerColor;
|
||||
|
||||
@ -71,7 +73,7 @@ struct TerrainTileObject
|
||||
const CGObjectInstance *obj;
|
||||
SDL_Rect rect;
|
||||
int fadeAnimKey;
|
||||
|
||||
|
||||
TerrainTileObject(const CGObjectInstance *obj_, SDL_Rect rect_);
|
||||
~TerrainTileObject();
|
||||
};
|
||||
@ -90,7 +92,7 @@ struct MapDrawingInfo
|
||||
int3 &topTile; // top-left tile in viewport [in tiles]
|
||||
const std::vector< std::vector< std::vector<ui8> > > * visibilityMap;
|
||||
SDL_Rect * drawBounds; // map rect drawing bounds on screen
|
||||
CDefHandler * iconsDef; // holds overlay icons for world view mode
|
||||
std::shared_ptr<CAnimation> icons; // holds overlay icons for world view mode
|
||||
float scale; // map scale for world view mode (only if scaled == true)
|
||||
|
||||
bool otherheroAnim;
|
||||
@ -101,17 +103,17 @@ struct MapDrawingInfo
|
||||
|
||||
bool puzzleMode;
|
||||
int3 grailPos; // location of grail for puzzle mode [in tiles]
|
||||
|
||||
|
||||
const std::vector<ObjectPosInfo> * additionalIcons;
|
||||
|
||||
|
||||
bool showAllTerrain; //for expert viewEarth
|
||||
|
||||
MapDrawingInfo(int3 &topTile_, const std::vector< std::vector< std::vector<ui8> > > * visibilityMap_, SDL_Rect * drawBounds_, CDefHandler * iconsDef_ = nullptr)
|
||||
|
||||
MapDrawingInfo(int3 &topTile_, const std::vector< std::vector< std::vector<ui8> > > * visibilityMap_, SDL_Rect * drawBounds_, std::shared_ptr<CAnimation> icons_ = nullptr)
|
||||
: scaled(false),
|
||||
topTile(topTile_),
|
||||
visibilityMap(visibilityMap_),
|
||||
drawBounds(drawBounds_),
|
||||
iconsDef(iconsDef_),
|
||||
icons(icons_),
|
||||
scale(1.0f),
|
||||
otherheroAnim(false),
|
||||
anim(0u),
|
||||
@ -188,14 +190,14 @@ class CMapHandler
|
||||
SDL_Surface * cacheWorldViewEntry(EMapCacheType type, intptr_t key, SDL_Surface * entry);
|
||||
intptr_t genKey(intptr_t realPtr, ui8 mod);
|
||||
};
|
||||
|
||||
|
||||
/// helper struct to pass around resolved bitmaps of an object; surfaces can be nullptr if object doesn't have bitmap of that type
|
||||
struct AnimBitmapHolder
|
||||
{
|
||||
SDL_Surface * objBitmap; // main object bitmap
|
||||
SDL_Surface * flagBitmap; // flag bitmap for the object (probably only for heroes and boats with heroes)
|
||||
bool isMoving; // indicates if the object is moving (again, heroes/boats only)
|
||||
|
||||
|
||||
AnimBitmapHolder(SDL_Surface * objBitmap_ = nullptr, SDL_Surface * flagBitmap_ = nullptr, bool moving = false)
|
||||
: objBitmap(objBitmap_),
|
||||
flagBitmap(flagBitmap_),
|
||||
@ -205,7 +207,7 @@ class CMapHandler
|
||||
|
||||
|
||||
class CMapBlitter
|
||||
{
|
||||
{
|
||||
protected:
|
||||
const int FRAMES_PER_MOVE_ANIM_GROUP = 8;
|
||||
CMapHandler * parent; // ptr to enclosing map handler; generally for legacy reasons, probably could/should be refactored out of here
|
||||
@ -267,16 +269,16 @@ class CMapHandler
|
||||
|
||||
virtual bool canDrawObject(const CGObjectInstance * obj) const;
|
||||
virtual bool canDrawCurrentTile() const;
|
||||
|
||||
|
||||
// internal helper methods to choose correct bitmap(s) for object; called internally by findObjectBitmap
|
||||
AnimBitmapHolder findHeroBitmap(const CGHeroInstance * hero, int anim) const;
|
||||
AnimBitmapHolder findBoatBitmap(const CGBoat * hero, int anim) const;
|
||||
AnimBitmapHolder findBoatBitmap(const CGBoat * hero, int anim) const;
|
||||
SDL_Surface * findFlagBitmap(const CGHeroInstance * obj, int anim, const PlayerColor * color, int indexOffset) const;
|
||||
SDL_Surface * findHeroFlagBitmap(const CGHeroInstance * obj, int anim, const PlayerColor * color, int indexOffset) const;
|
||||
SDL_Surface * findBoatFlagBitmap(const CGBoat * obj, int anim, const PlayerColor * color, int indexOffset, ui8 dir) const;
|
||||
SDL_Surface * findFlagBitmapInternal(const CDefEssential * def, int anim, int indexOffset, ui8 dir, bool moving) const;
|
||||
int findAnimIndexByGroup(const CDefEssential * def, int groupNum) const;
|
||||
|
||||
|
||||
public:
|
||||
CMapBlitter(CMapHandler * p) : parent(p) {}
|
||||
virtual ~CMapBlitter(){}
|
||||
@ -303,7 +305,7 @@ class CMapHandler
|
||||
class CMapWorldViewBlitter : public CMapBlitter
|
||||
{
|
||||
private:
|
||||
SDL_Surface * objectToIcon(Obj id, si32 subId, PlayerColor owner) const;
|
||||
IImage * objectToIcon(Obj id, si32 subId, PlayerColor owner) const;
|
||||
protected:
|
||||
void drawElement(EMapCacheType cacheType, SDL_Surface * sourceSurf, SDL_Rect * sourceRect,
|
||||
SDL_Surface * targetSurf, SDL_Rect * destRect, bool alphaBlit = false, ui8 rotationInfo = 0u) const override;
|
||||
@ -312,7 +314,7 @@ class CMapHandler
|
||||
void drawHeroFlag(SDL_Surface * targetSurf, SDL_Surface * sourceSurf, SDL_Rect * sourceRect, SDL_Rect * destRect, bool moving) const override;
|
||||
void drawObject(SDL_Surface * targetSurf, SDL_Surface * sourceSurf, SDL_Rect * sourceRect, bool moving) const override;
|
||||
void drawFrame(SDL_Surface * targetSurf) const override {}
|
||||
void drawOverlayEx(SDL_Surface * targetSurf);
|
||||
void drawOverlayEx(SDL_Surface * targetSurf) override;
|
||||
void init(const MapDrawingInfo * info) override;
|
||||
SDL_Rect clip(SDL_Surface * targetSurf) const override;
|
||||
|
||||
@ -344,7 +346,7 @@ class CMapHandler
|
||||
CMapBlitter * normalBlitter;
|
||||
CMapBlitter * worldViewBlitter;
|
||||
CMapBlitter * puzzleViewBlitter;
|
||||
|
||||
|
||||
std::map<int, std::pair<int3, CFadeAnimation*>> fadeAnims;
|
||||
int fadeAnimCounter;
|
||||
|
||||
@ -386,7 +388,7 @@ public:
|
||||
|
||||
void getTerrainDescr(const int3 &pos, std::string & out, bool terName); //if tername == false => empty string when tile is clear
|
||||
CGObjectInstance * createObject(int id, int subid, int3 pos, int owner=254); //creates a new object with a certain id and subid
|
||||
bool printObject(const CGObjectInstance * obj, bool fadein = false); //puts appropriate things to ttiles, so obj will be visible on map
|
||||
bool printObject(const CGObjectInstance * obj, bool fadein = false); //puts appropriate things to tiles, so obj will be visible on map
|
||||
bool hideObject(const CGObjectInstance * obj, bool fadeout = false); //removes appropriate things from ttiles, so obj will be no longer visible on map (but still will exist)
|
||||
bool removeObject(CGObjectInstance * obj, bool fadeout = false); //removes object from each place in VCMI (I hope)
|
||||
void init();
|
||||
|
@ -17,6 +17,8 @@
|
||||
#include "../gui/CGuiHandler.h"
|
||||
#include "../gui/SDL_Pixels.h"
|
||||
|
||||
#include "../widgets/Images.h"
|
||||
|
||||
#include "../windows/InfoWindows.h"
|
||||
#include "../windows/CAdvmapInterface.h"
|
||||
#include "../windows/GUIClasses.h"
|
||||
@ -1121,24 +1123,11 @@ void CInGameConsole::keyPressed (const SDL_KeyboardEvent & key)
|
||||
}
|
||||
default:
|
||||
{
|
||||
#ifdef VCMI_SDL1
|
||||
if(enteredText.size() > 0 && enteredText.size() < conf.go()->ac.inputLineLength)
|
||||
{
|
||||
if( key.keysym.unicode < 0x80 && key.keysym.unicode > 0 )
|
||||
{
|
||||
enteredText[enteredText.size()-1] = (char)key.keysym.unicode;
|
||||
enteredText += "_";
|
||||
refreshEnteredText();
|
||||
}
|
||||
}
|
||||
#endif // VCMI_SDL1
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef VCMI_SDL1
|
||||
|
||||
void CInGameConsole::textInputed(const SDL_TextInputEvent & event)
|
||||
{
|
||||
if(!captureAllKeys || enteredText.size() == 0)
|
||||
@ -1156,8 +1145,6 @@ void CInGameConsole::textEdited(const SDL_TextEditingEvent & event)
|
||||
//do nothing here
|
||||
}
|
||||
|
||||
#endif // VCMI_SDL1
|
||||
|
||||
void CInGameConsole::startEnteringText()
|
||||
{
|
||||
CSDL_Ext::startTextInput(&pos);
|
||||
@ -1219,14 +1206,9 @@ void CInGameConsole::refreshEnteredText()
|
||||
|
||||
CInGameConsole::CInGameConsole() : prevEntDisp(-1), defaultTimeout(10000), maxDisplayedTexts(10)
|
||||
{
|
||||
#ifdef VCMI_SDL1
|
||||
addUsedEvents(KEYBOARD);
|
||||
#else
|
||||
addUsedEvents(KEYBOARD | TEXTINPUT);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
CAdvMapPanel::CAdvMapPanel(SDL_Surface * bg, Point position)
|
||||
: CIntObject(),
|
||||
background(bg)
|
||||
@ -1276,11 +1258,11 @@ void CAdvMapPanel::addChildToPanel(CIntObject * obj, ui8 actions /* = 0 */)
|
||||
addChild(obj, false);
|
||||
}
|
||||
|
||||
CAdvMapWorldViewPanel::CAdvMapWorldViewPanel(SDL_Surface * bg, Point position, int spaceBottom, const PlayerColor &color)
|
||||
: CAdvMapPanel(bg, position)
|
||||
CAdvMapWorldViewPanel::CAdvMapWorldViewPanel(std::shared_ptr<CAnimation> _icons, SDL_Surface * bg, Point position, int spaceBottom, const PlayerColor &color)
|
||||
: CAdvMapPanel(bg, position), icons(_icons)
|
||||
{
|
||||
fillerHeight = bg ? spaceBottom - pos.y - pos.h : 0;
|
||||
|
||||
|
||||
if (fillerHeight > 0)
|
||||
{
|
||||
tmpBackgroundFiller = CMessage::drawDialogBox(pos.w, fillerHeight, color);
|
||||
@ -1295,23 +1277,16 @@ CAdvMapWorldViewPanel::~CAdvMapWorldViewPanel()
|
||||
SDL_FreeSurface(tmpBackgroundFiller);
|
||||
}
|
||||
|
||||
void CAdvMapWorldViewPanel::recolorIcons(const PlayerColor &color, const CDefHandler *def, int indexOffset)
|
||||
void CAdvMapWorldViewPanel::recolorIcons(const PlayerColor &color, int indexOffset)
|
||||
{
|
||||
for (auto &pic : currentIcons)
|
||||
{
|
||||
removeChild(pic);
|
||||
delete pic;
|
||||
}
|
||||
currentIcons.clear();
|
||||
assert(iconsData.size() == currentIcons.size());
|
||||
|
||||
for (auto &data : iconsData)
|
||||
for(size_t idx = 0; idx < iconsData.size(); idx++)
|
||||
{
|
||||
auto pic = new CPicture(def->ourImages[data.first + indexOffset].bitmap, data.second.x, data.second.y, false);
|
||||
pic->recActions |= SHOWALL;
|
||||
currentIcons.push_back(pic);
|
||||
addChildToPanel(pic);
|
||||
const auto & data = iconsData.at(idx);
|
||||
currentIcons[idx]->setFrame(data.first + indexOffset);
|
||||
}
|
||||
|
||||
|
||||
if (fillerHeight > 0)
|
||||
{
|
||||
if (tmpBackgroundFiller)
|
||||
@ -1320,18 +1295,17 @@ void CAdvMapWorldViewPanel::recolorIcons(const PlayerColor &color, const CDefHan
|
||||
}
|
||||
}
|
||||
|
||||
void CAdvMapWorldViewPanel::addChildIcon(std::pair<int, Point> data, const CDefHandler *def, int indexOffset)
|
||||
void CAdvMapWorldViewPanel::addChildIcon(std::pair<int, Point> data, int indexOffset)
|
||||
{
|
||||
OBJ_CONSTRUCTION_CAPTURING_ALL;
|
||||
iconsData.push_back(data);
|
||||
auto pic = new CPicture(def->ourImages[data.first + indexOffset].bitmap, data.second.x, data.second.y, false);
|
||||
currentIcons.push_back(pic);
|
||||
addChildToPanel(pic);
|
||||
currentIcons.push_back(new CAnimImage(icons, data.first + indexOffset, 0, data.second.x, data.second.y));
|
||||
}
|
||||
|
||||
void CAdvMapWorldViewPanel::showAll(SDL_Surface * to)
|
||||
{
|
||||
if (tmpBackgroundFiller)
|
||||
{
|
||||
{
|
||||
blitAt(tmpBackgroundFiller, pos.x, pos.y + pos.h, to);
|
||||
}
|
||||
|
||||
|
@ -4,6 +4,8 @@
|
||||
#include "../../lib/FunctionList.h"
|
||||
|
||||
class CArmedInstance;
|
||||
class CAnimation;
|
||||
class CAnimImage;
|
||||
class CShowableAnim;
|
||||
class CGGarrison;
|
||||
class CGObjectInstance;
|
||||
@ -37,9 +39,9 @@ protected:
|
||||
CListItem(CList * parent);
|
||||
~CListItem();
|
||||
|
||||
void clickRight(tribool down, bool previousState);
|
||||
void clickLeft(tribool down, bool previousState);
|
||||
void hover(bool on);
|
||||
void clickRight(tribool down, bool previousState) override;
|
||||
void clickLeft(tribool down, bool previousState) override;
|
||||
void hover(bool on) override;
|
||||
void onSelect(bool on);
|
||||
|
||||
/// create object with selection rectangle
|
||||
@ -118,12 +120,12 @@ class CHeroList : public CList
|
||||
|
||||
CHeroItem(CHeroList *parent, const CGHeroInstance * hero);
|
||||
|
||||
CIntObject * genSelection();
|
||||
CIntObject * genSelection() override;
|
||||
void update();
|
||||
void select(bool on);
|
||||
void open();
|
||||
void showTooltip();
|
||||
std::string getHoverText();
|
||||
void select(bool on) override;
|
||||
void open() override;
|
||||
void showTooltip() override;
|
||||
std::string getHoverText() override;
|
||||
};
|
||||
|
||||
CIntObject * createHeroItem(size_t index);
|
||||
@ -152,12 +154,12 @@ class CTownList : public CList
|
||||
|
||||
CTownItem(CTownList *parent, const CGTownInstance * town);
|
||||
|
||||
CIntObject * genSelection();
|
||||
CIntObject * genSelection() override;
|
||||
void update();
|
||||
void select(bool on);
|
||||
void open();
|
||||
void showTooltip();
|
||||
std::string getHoverText();
|
||||
void select(bool on) override;
|
||||
void open() override;
|
||||
void showTooltip() override;
|
||||
std::string getHoverText() override;
|
||||
};
|
||||
|
||||
CIntObject * createTownItem(size_t index);
|
||||
@ -195,7 +197,7 @@ public:
|
||||
CMinimapInstance(CMinimap * parent, int level);
|
||||
~CMinimapInstance();
|
||||
|
||||
void showAll(SDL_Surface *to);
|
||||
void showAll(SDL_Surface *to) override;
|
||||
void tileToPixels (const int3 &tile, int &x, int &y,int toX = 0, int toY = 0);
|
||||
|
||||
void refreshTile(const int3 &pos);
|
||||
@ -213,10 +215,10 @@ protected:
|
||||
//to initialize colors
|
||||
std::map<int, std::pair<SDL_Color, SDL_Color> > loadColors(std::string from);
|
||||
|
||||
void clickLeft(tribool down, bool previousState);
|
||||
void clickRight(tribool down, bool previousState);
|
||||
void hover (bool on);
|
||||
void mouseMoved (const SDL_MouseMotionEvent & sEvent);
|
||||
void clickLeft(tribool down, bool previousState) override;
|
||||
void clickRight(tribool down, bool previousState) override;
|
||||
void hover (bool on) override;
|
||||
void mouseMoved (const SDL_MouseMotionEvent & sEvent) override;
|
||||
|
||||
void moveAdvMapSelection();
|
||||
|
||||
@ -232,7 +234,7 @@ public:
|
||||
void setLevel(int level);
|
||||
void setAIRadar(bool on);
|
||||
|
||||
void showAll(SDL_Surface * to);
|
||||
void showAll(SDL_Surface * to) override;
|
||||
|
||||
void hideTile(const int3 &pos); //puts FoW
|
||||
void showTile(const int3 &pos); //removes FoW
|
||||
@ -256,7 +258,7 @@ class CInfoBar : public CIntObject
|
||||
public:
|
||||
CVisibleInfo(Point position);
|
||||
|
||||
void show(SDL_Surface *to);
|
||||
void show(SDL_Surface *to) override;
|
||||
|
||||
//functions that must be called only once
|
||||
void loadHero(const CGHeroInstance * hero);
|
||||
@ -283,11 +285,11 @@ class CInfoBar : public CIntObject
|
||||
//removes all information about current state, deactivates timer (if any)
|
||||
void reset(EState newState);
|
||||
|
||||
void tick();
|
||||
void tick() override;
|
||||
|
||||
void clickLeft(tribool down, bool previousState);
|
||||
void clickRight(tribool down, bool previousState);
|
||||
void hover(bool on);
|
||||
void clickLeft(tribool down, bool previousState) override;
|
||||
void clickRight(tribool down, bool previousState) override;
|
||||
void hover(bool on) override;
|
||||
|
||||
public:
|
||||
CInfoBar(const Rect & pos);
|
||||
@ -331,7 +333,7 @@ public:
|
||||
/// recolors all buttons to given player color
|
||||
void setPlayerColor(const PlayerColor & clr);
|
||||
|
||||
void showAll(SDL_Surface * to);
|
||||
void showAll(SDL_Surface * to) override;
|
||||
};
|
||||
|
||||
/// specialized version of CAdvMapPanel that handles recolorable def-based pictures for world view info panel
|
||||
@ -340,18 +342,19 @@ class CAdvMapWorldViewPanel : public CAdvMapPanel
|
||||
/// data that allows reconstruction of panel info icons
|
||||
std::vector<std::pair<int, Point>> iconsData;
|
||||
/// ptrs to child-pictures constructed from iconsData
|
||||
std::vector<CPicture *> currentIcons;
|
||||
std::vector<CAnimImage *> currentIcons;
|
||||
/// temporary surface drawn below world view panel on higher resolutions (won't be needed when world view panel is configured for extraResolutions mod)
|
||||
SDL_Surface * tmpBackgroundFiller;
|
||||
int fillerHeight;
|
||||
std::shared_ptr<CAnimation> icons;
|
||||
public:
|
||||
CAdvMapWorldViewPanel(SDL_Surface * bg, Point position, int spaceBottom, const PlayerColor &color);
|
||||
CAdvMapWorldViewPanel(std::shared_ptr<CAnimation> _icons, SDL_Surface * bg, Point position, int spaceBottom, const PlayerColor &color);
|
||||
virtual ~CAdvMapWorldViewPanel();
|
||||
|
||||
void addChildIcon(std::pair<int, Point> data, const CDefHandler *def, int indexOffset);
|
||||
void addChildIcon(std::pair<int, Point> data, int indexOffset);
|
||||
/// recreates all pictures from given def to recolor them according to current player color
|
||||
void recolorIcons(const PlayerColor &color, const CDefHandler *def, int indexOffset);
|
||||
void showAll(SDL_Surface * to);
|
||||
void recolorIcons(const PlayerColor &color, int indexOffset);
|
||||
void showAll(SDL_Surface * to) override;
|
||||
};
|
||||
|
||||
class CInGameConsole : public CIntObject
|
||||
@ -365,14 +368,12 @@ private:
|
||||
int maxDisplayedTexts; //hiw many texts can be displayed simultaneously
|
||||
public:
|
||||
std::string enteredText;
|
||||
void show(SDL_Surface * to);
|
||||
void show(SDL_Surface * to) override;
|
||||
void print(const std::string &txt);
|
||||
void keyPressed (const SDL_KeyboardEvent & key); //call-in
|
||||
void keyPressed (const SDL_KeyboardEvent & key) override; //call-in
|
||||
|
||||
#ifndef VCMI_SDL1
|
||||
void textInputed(const SDL_TextInputEvent & event) override;
|
||||
void textEdited(const SDL_TextEditingEvent & event) override;
|
||||
#endif // VCMI_SDL1
|
||||
|
||||
void startEnteringText();
|
||||
void endEnteringText(bool printEnteredText);
|
||||
|
@ -209,10 +209,10 @@ void CButton::hover (bool on)
|
||||
setState(PRESSED);*/
|
||||
|
||||
std::string name = hoverTexts[getState()].empty()
|
||||
? hoverTexts[getState()]
|
||||
: hoverTexts[0];
|
||||
? hoverTexts[0]
|
||||
: hoverTexts[getState()];
|
||||
|
||||
if(!name.empty() && !isBlocked()) //if there is no name, there is nohing to display also
|
||||
if(!name.empty() && !isBlocked()) //if there is no name, there is nothing to display also
|
||||
{
|
||||
if (LOCPLINT && LOCPLINT->battleInt) //for battle buttons
|
||||
{
|
||||
@ -272,10 +272,11 @@ void CButton::setIndex(size_t index, bool playerColoredButton)
|
||||
if (index == currentImage || index>=imageNames.size())
|
||||
return;
|
||||
currentImage = index;
|
||||
setImage(new CAnimation(imageNames[index]), playerColoredButton);
|
||||
auto anim = std::make_shared<CAnimation>(imageNames[index]);
|
||||
setImage(anim, playerColoredButton);
|
||||
}
|
||||
|
||||
void CButton::setImage(CAnimation* anim, bool playerColoredButton, int animFlags)
|
||||
void CButton::setImage(std::shared_ptr<CAnimation> anim, bool playerColoredButton, int animFlags)
|
||||
{
|
||||
OBJ_CONSTRUCTION_CAPTURING_ALL;
|
||||
|
||||
@ -294,14 +295,9 @@ void CButton::setPlayerColor(PlayerColor player)
|
||||
void CButton::showAll(SDL_Surface * to)
|
||||
{
|
||||
CIntObject::showAll(to);
|
||||
|
||||
#ifdef VCMI_SDL1
|
||||
if (borderColor && borderColor->unused == 0)
|
||||
CSDL_Ext::drawBorder(to, pos.x-1, pos.y-1, pos.w+2, pos.h+2, int3(borderColor->r, borderColor->g, borderColor->b));
|
||||
#else
|
||||
|
||||
if (borderColor && borderColor->a == 0)
|
||||
CSDL_Ext::drawBorder(to, pos.x-1, pos.y-1, pos.w+2, pos.h+2, int3(borderColor->r, borderColor->g, borderColor->b));
|
||||
#endif // 0
|
||||
}
|
||||
|
||||
std::pair<std::string, std::string> CButton::tooltip()
|
||||
@ -424,8 +420,8 @@ void CToggleGroup::addToggle(int identifier, CToggleBase* bt)
|
||||
buttons[identifier] = bt;
|
||||
}
|
||||
|
||||
CToggleGroup::CToggleGroup(const CFunctionList<void(int)> &OnChange, bool musicLikeButtons)
|
||||
: onChange(OnChange), selectedID(-2), musicLike(musicLikeButtons)
|
||||
CToggleGroup::CToggleGroup(const CFunctionList<void(int)> &OnChange)
|
||||
: onChange(OnChange), selectedID(-2)
|
||||
{}
|
||||
|
||||
void CToggleGroup::setSelected(int id)
|
||||
@ -452,26 +448,86 @@ void CToggleGroup::selectionChanged(int to)
|
||||
parent->redraw();
|
||||
}
|
||||
|
||||
void CToggleGroup::show(SDL_Surface * to)
|
||||
CVolumeSlider::CVolumeSlider(const Point &position, const std::string &defName, const int value,
|
||||
const std::pair<std::string, std::string> * const help) :
|
||||
value(value),
|
||||
helpHandlers(help)
|
||||
{
|
||||
if (musicLike)
|
||||
{
|
||||
if (auto intObj = dynamic_cast<CIntObject*>(buttons[selectedID])) // hack-ish workagound to avoid diamond problem with inheritance
|
||||
intObj->show(to);
|
||||
}
|
||||
else
|
||||
CIntObject::show(to);
|
||||
OBJ_CONSTRUCTION_CAPTURING_ALL;
|
||||
animImage = new CAnimImage(std::make_shared<CAnimation>(defName), 0, 0, position.x, position.y),
|
||||
assert(!defName.empty());
|
||||
addUsedEvents(LCLICK | RCLICK | WHEEL);
|
||||
pos.x += position.x;
|
||||
pos.y += position.y;
|
||||
pos.w = (animImage->pos.w + 1) * animImage->size();
|
||||
pos.h = animImage->pos.h;
|
||||
type |= REDRAW_PARENT;
|
||||
setVolume(value);
|
||||
}
|
||||
|
||||
void CToggleGroup::showAll(SDL_Surface * to)
|
||||
void CVolumeSlider::setVolume(int value_)
|
||||
{
|
||||
if (musicLike)
|
||||
value = value_;
|
||||
moveTo(value * static_cast<double>(animImage->size()) / 100.0);
|
||||
}
|
||||
|
||||
void CVolumeSlider::moveTo(int id)
|
||||
{
|
||||
vstd::abetween(id, 0, animImage->size() - 1);
|
||||
animImage->setFrame(id);
|
||||
animImage->moveTo(Point(pos.x + (animImage->pos.w + 1) * id, pos.y));
|
||||
if (active)
|
||||
redraw();
|
||||
}
|
||||
|
||||
void CVolumeSlider::addCallback(std::function<void(int)> callback)
|
||||
{
|
||||
onChange += callback;
|
||||
}
|
||||
|
||||
void CVolumeSlider::clickLeft(tribool down, bool previousState)
|
||||
{
|
||||
if (down)
|
||||
{
|
||||
if (auto intObj = dynamic_cast<CIntObject*>(buttons[selectedID])) // hack-ish workagound to avoid diamond problem with inheritance
|
||||
intObj->showAll(to);
|
||||
double px = GH.current->motion.x - pos.x;
|
||||
double rx = px / static_cast<double>(pos.w);
|
||||
// setVolume is out of 100
|
||||
setVolume(rx * 100);
|
||||
// Volume config is out of 100, set to increments of 5ish roughly based on the half point of the indicator
|
||||
// 0.0 -> 0, 0.05 -> 5, 0.09 -> 5,...,
|
||||
// 0.1 -> 10, ..., 0.19 -> 15, 0.2 -> 20, ...,
|
||||
// 0.28 -> 25, 0.29 -> 30, 0.3 -> 30, ...,
|
||||
// 0.85 -> 85, 0.86 -> 90, ..., 0.87 -> 90,...,
|
||||
// 0.95 -> 95, 0.96 -> 100, 0.99 -> 100
|
||||
int volume = 5 * int(rx * (2 * animImage->size() + 1));
|
||||
onChange(volume);
|
||||
}
|
||||
}
|
||||
|
||||
void CVolumeSlider::clickRight(tribool down, bool previousState)
|
||||
{
|
||||
if (down)
|
||||
{
|
||||
double px = GH.current->motion.x - pos.x;
|
||||
int index = px / static_cast<double>(pos.w) * animImage->size();
|
||||
std::string hoverText = helpHandlers[index].first;
|
||||
std::string helpBox = helpHandlers[index].second;
|
||||
if(!helpBox.empty())
|
||||
CRClickPopup::createAndPush(helpBox);
|
||||
if(GH.statusbar)
|
||||
GH.statusbar->setText(helpBox);
|
||||
}
|
||||
}
|
||||
|
||||
void CVolumeSlider::wheelScrolled(bool down, bool in)
|
||||
{
|
||||
if (in)
|
||||
{
|
||||
int volume = value + 3 * (down ? 1 : -1);
|
||||
vstd::abetween(volume, 0, 100);
|
||||
setVolume(volume);
|
||||
onChange(volume);
|
||||
}
|
||||
else
|
||||
CIntObject::showAll(to);
|
||||
}
|
||||
|
||||
void CSlider::sliderClicked()
|
||||
|
@ -10,7 +10,6 @@ struct Rect;
|
||||
class CAnimImage;
|
||||
class CLabel;
|
||||
class CAnimation;
|
||||
class CDefHandler;
|
||||
|
||||
namespace config
|
||||
{
|
||||
@ -111,7 +110,7 @@ public:
|
||||
|
||||
/// Appearance modifiers
|
||||
void setIndex(size_t index, bool playerColoredButton=false);
|
||||
void setImage(CAnimation* anim, bool playerColoredButton=false, int animFlags=0);
|
||||
void setImage(std::shared_ptr<CAnimation> anim, bool playerColoredButton=false, int animFlags=0);
|
||||
void setPlayerColor(PlayerColor player);
|
||||
|
||||
/// CIntObject overrides
|
||||
@ -178,12 +177,11 @@ class CToggleGroup : public CIntObject
|
||||
CFunctionList<void(int)> onChange; //called when changing selected button with new button's id
|
||||
|
||||
int selectedID;
|
||||
bool musicLike; //determines the behaviour of this group
|
||||
void selectionChanged(int to);
|
||||
public:
|
||||
std::map<int, CToggleBase*> buttons;
|
||||
|
||||
CToggleGroup(const CFunctionList<void(int)> & OnChange, bool musicLikeButtons = false);
|
||||
CToggleGroup(const CFunctionList<void(int)> & OnChange);
|
||||
|
||||
void addCallback(std::function<void(int)> callback);
|
||||
|
||||
@ -191,9 +189,32 @@ public:
|
||||
void addToggle(int index, CToggleBase * button);
|
||||
/// Changes selection to specific value. Will select toggle with this ID, if present
|
||||
void setSelected(int id);
|
||||
};
|
||||
|
||||
void show(SDL_Surface * to);
|
||||
void showAll(SDL_Surface * to);
|
||||
/// A typical slider for volume with an animated indicator
|
||||
class CVolumeSlider : public CIntObject
|
||||
{
|
||||
int value;
|
||||
CFunctionList<void(int)> onChange;
|
||||
CAnimImage * animImage;
|
||||
const std::pair<std::string, std::string> * const helpHandlers;
|
||||
void setVolume(const int v);
|
||||
public:
|
||||
|
||||
/// @param position coordinates of slider
|
||||
/// @param defName name of def animation for slider
|
||||
/// @param value initial value for volume
|
||||
/// @param help pointer to first helptext of slider
|
||||
CVolumeSlider(const Point &position, const std::string &defName, const int value,
|
||||
const std::pair<std::string, std::string> * const help);
|
||||
|
||||
void moveTo(int id);
|
||||
void addCallback(std::function<void(int)> callback);
|
||||
|
||||
|
||||
void clickLeft(tribool down, bool previousState) override;
|
||||
void clickRight(tribool down, bool previousState) override;
|
||||
void wheelScrolled(bool down, bool in) override;
|
||||
};
|
||||
|
||||
/// A typical slider which can be orientated horizontally/vertically.
|
||||
@ -242,20 +263,18 @@ public:
|
||||
|
||||
void addCallback(std::function<void(int)> callback);
|
||||
|
||||
void keyPressed(const SDL_KeyboardEvent & key);
|
||||
void wheelScrolled(bool down, bool in);
|
||||
void clickLeft(tribool down, bool previousState);
|
||||
void mouseMoved (const SDL_MouseMotionEvent & sEvent);
|
||||
void showAll(SDL_Surface * to);
|
||||
void keyPressed(const SDL_KeyboardEvent & key) override;
|
||||
void wheelScrolled(bool down, bool in) override;
|
||||
void clickLeft(tribool down, bool previousState) override;
|
||||
void mouseMoved (const SDL_MouseMotionEvent & sEvent) override;
|
||||
void showAll(SDL_Surface * to) override;
|
||||
|
||||
/**
|
||||
* @param position, coordinates of slider
|
||||
* @param length, length of slider ribbon, including left/right buttons
|
||||
* @param Moved, function that will be called whenever slider moves
|
||||
* @param Capacity, maximal number of visible at once elements
|
||||
* @param Amount, total amount of elements, including not visible
|
||||
* @param Value, starting position
|
||||
*/
|
||||
/// @param position coordinates of slider
|
||||
/// @param length length of slider ribbon, including left/right buttons
|
||||
/// @param Moved function that will be called whenever slider moves
|
||||
/// @param Capacity maximal number of visible at once elements
|
||||
/// @param Amount total amount of elements, including not visible
|
||||
/// @param Value starting position
|
||||
CSlider(Point position, int length, std::function<void(int)> Moved, int Capacity, int Amount,
|
||||
int Value=0, bool Horizontal=true, EStyle style = BROWN);
|
||||
~CSlider();
|
||||
|
@ -32,7 +32,7 @@
|
||||
*/
|
||||
|
||||
CArtPlace::CArtPlace(Point position, const CArtifactInstance * Art):
|
||||
locked(false), picked(false), marked(false), ourArt(Art)
|
||||
locked(false), picked(false), marked(false), ourArt(Art)
|
||||
{
|
||||
pos += position;
|
||||
pos.w = pos.h = 44;
|
||||
@ -123,10 +123,7 @@ void CArtPlace::clickLeft(tribool down, bool previousState)
|
||||
if(ourArt && !down && previousState && !ourOwner->commonInfo->src.AOH)
|
||||
{
|
||||
if(ourArt->artType->id == ArtifactID::SPELLBOOK)
|
||||
{
|
||||
auto spellWindow = new CSpellWindow(genRect(595, 620, (screen->w - 620)/2, (screen->h - 595)/2), ourOwner->curHero, LOCPLINT, LOCPLINT->battleInt);
|
||||
GH.pushInt(spellWindow);
|
||||
}
|
||||
GH.pushInt(new CSpellWindow(ourOwner->curHero, LOCPLINT, LOCPLINT->battleInt));
|
||||
}
|
||||
|
||||
if (!down && previousState)
|
||||
@ -180,7 +177,7 @@ void CArtPlace::clickLeft(tribool down, bool previousState)
|
||||
if(srcInBackpack && srcInSameHero)
|
||||
{
|
||||
if(!ourArt //cannot move from backpack to AFTER backpack -> combined with vstd::amin above it will guarantee that dest is at most the last artifact
|
||||
|| ourOwner->commonInfo->src.slotID < ourOwner->commonInfo->dst.slotID) //rearranging arts in backpack after taking src artifact, the dest id will be shifted
|
||||
|| ourOwner->commonInfo->src.slotID < ourOwner->commonInfo->dst.slotID) //rearranging arts in backpack after taking src artifact, the dest id will be shifted
|
||||
vstd::advance(ourOwner->commonInfo->dst.slotID, -1);
|
||||
}
|
||||
if(srcInSameHero && ourOwner->commonInfo->dst.slotID == ourOwner->commonInfo->src.slotID) //we came to src == dst
|
||||
@ -214,6 +211,34 @@ void CArtPlace::clickLeft(tribool down, bool previousState)
|
||||
}
|
||||
}
|
||||
|
||||
bool CArtPlace::askToAssemble(const CArtifactInstance *art, ArtifactPosition slot,
|
||||
const CGHeroInstance *hero)
|
||||
{
|
||||
assert(art != nullptr);
|
||||
assert(hero != nullptr);
|
||||
std::vector<const CArtifact *> assemblyPossibilities = art->assemblyPossibilities(hero);
|
||||
|
||||
// If the artifact can be assembled, display dialog.
|
||||
for(const CArtifact *combination : assemblyPossibilities)
|
||||
{
|
||||
LOCPLINT->showArtifactAssemblyDialog(
|
||||
art->artType->id,
|
||||
combination->id,
|
||||
true,
|
||||
std::bind(&CCallback::assembleArtifacts, LOCPLINT->cb.get(), hero, slot, true, combination->id),
|
||||
0);
|
||||
|
||||
if(assemblyPossibilities.size() > 2)
|
||||
{
|
||||
logGlobal->warnStream() << boost::format(
|
||||
"More than one possibility of assembling on %s... taking only first")
|
||||
% art->artType->Name();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void CArtPlace::clickRight(tribool down, bool previousState)
|
||||
{
|
||||
if(down && ourArt && !locked && text.size() && !picked) //if there is no description or it's a lock, do nothing ;]
|
||||
@ -225,20 +250,8 @@ void CArtPlace::clickRight(tribool down, bool previousState)
|
||||
std::vector<const CArtifact *> assemblyPossibilities = ourArt->assemblyPossibilities(ourOwner->curHero);
|
||||
|
||||
// If the artifact can be assembled, display dialog.
|
||||
for(const CArtifact *combination : assemblyPossibilities)
|
||||
if (askToAssemble(ourArt, slotID, ourOwner->curHero))
|
||||
{
|
||||
LOCPLINT->showArtifactAssemblyDialog(
|
||||
ourArt->artType->id,
|
||||
combination->id,
|
||||
true,
|
||||
std::bind(&CCallback::assembleArtifacts, LOCPLINT->cb.get(), ourOwner->curHero, slotID, true, combination->id),
|
||||
0);
|
||||
|
||||
if(assemblyPossibilities.size() > 2)
|
||||
{
|
||||
logGlobal->warnStream() << "More than one possibility of assembling... taking only first";
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@ -303,10 +316,10 @@ void CArtPlace::deselect ()
|
||||
for(int i = 0; i < GameConstants::BACKPACK_START; i++)
|
||||
{
|
||||
auto place = ourOwner->getArtPlace(i);
|
||||
|
||||
|
||||
if(nullptr != place)//getArtPlace may return null
|
||||
place->pickSlot(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CCS->curh->dragAndDropCursor(nullptr);
|
||||
@ -372,70 +385,36 @@ void CArtPlace::setArtifact(const CArtifactInstance *art)
|
||||
image->disable();
|
||||
text = std::string();
|
||||
hoverText = CGI->generaltexth->allTexts[507];
|
||||
return;
|
||||
}
|
||||
|
||||
image->enable();
|
||||
image->setFrame(locked ? ArtifactID::ART_LOCK : art->artType->iconIndex);
|
||||
|
||||
text = art->getEffectiveDescription(ourOwner->curHero);
|
||||
|
||||
if(art->artType->id == ArtifactID::SPELL_SCROLL)
|
||||
{
|
||||
int spellID = art->getGivenSpellID();
|
||||
if(spellID >= 0)
|
||||
{
|
||||
//add spell component info (used to provide a pic in r-click popup)
|
||||
baseType = CComponent::spell;
|
||||
type = spellID;
|
||||
bonusValue = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
image->enable();
|
||||
image->setFrame(locked ? ArtifactID::ART_LOCK : art->artType->iconIndex);
|
||||
|
||||
std::string artDesc = ourArt->artType->Description();
|
||||
if (vstd::contains (artDesc, '{'))
|
||||
text = artDesc;
|
||||
else
|
||||
text = '{' + ourArt->artType->Name() + "}\n\n" + artDesc; //workaround for new artifacts with single name, turns it to H3-style
|
||||
|
||||
if(art->artType->id == ArtifactID::SPELL_SCROLL)
|
||||
{
|
||||
// we expect scroll description to be like this: This scroll contains the [spell name] spell which is added into your spell book for as long as you carry the scroll.
|
||||
// so we want to replace text in [...] with a spell name
|
||||
// however other language versions don't have name placeholder at all, so we have to be careful
|
||||
int spellID = art->getGivenSpellID();
|
||||
size_t nameStart = text.find_first_of('[');
|
||||
size_t nameEnd = text.find_first_of(']', nameStart);
|
||||
if(spellID >= 0)
|
||||
{
|
||||
if(nameStart != std::string::npos && nameEnd != std::string::npos)
|
||||
text = text.replace(nameStart, nameEnd - nameStart + 1, CGI->spellh->objects[spellID]->name);
|
||||
|
||||
//add spell component info (used to provide a pic in r-click popup)
|
||||
baseType = CComponent::spell;
|
||||
type = spellID;
|
||||
bonusValue = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
baseType = CComponent::artifact;
|
||||
type = art->artType->id;
|
||||
bonusValue = 0;
|
||||
}
|
||||
if (art->artType->constituents) //display info about components of combined artifact
|
||||
{
|
||||
//TODO
|
||||
}
|
||||
else if (art->artType->constituentOf.size()) //display info about set
|
||||
{
|
||||
std::string artList;
|
||||
auto combinedArt = art->artType->constituentOf[0];
|
||||
text += "\n\n";
|
||||
text += "{" + combinedArt->Name() + "}";
|
||||
int wornArtifacts = 0;
|
||||
for (auto a : *combinedArt->constituents) //TODO: can the artifact be a part of more than one set?
|
||||
{
|
||||
artList += "\n" + a->Name();
|
||||
if (ourOwner->curHero->hasArt(a->id, true))
|
||||
wornArtifacts++;
|
||||
}
|
||||
text += " (" + boost::str(boost::format("%d") % wornArtifacts) + " / " +
|
||||
boost::str(boost::format("%d") % combinedArt->constituents->size()) + ")" + artList;
|
||||
//TODO: fancy colors and fonts for this text
|
||||
}
|
||||
|
||||
if (locked) // Locks should appear as empty.
|
||||
hoverText = CGI->generaltexth->allTexts[507];
|
||||
else
|
||||
hoverText = boost::str(boost::format(CGI->generaltexth->heroscrn[1]) % ourArt->artType->Name());
|
||||
baseType = CComponent::artifact;
|
||||
type = art->artType->id;
|
||||
bonusValue = 0;
|
||||
}
|
||||
|
||||
if (locked) // Locks should appear as empty.
|
||||
hoverText = CGI->generaltexth->allTexts[507];
|
||||
else
|
||||
hoverText = boost::str(boost::format(CGI->generaltexth->heroscrn[1]) % ourArt->artType->Name());
|
||||
}
|
||||
|
||||
void CArtifactsOfHero::SCommonPart::reset()
|
||||
@ -454,12 +433,12 @@ void CArtifactsOfHero::setHero(const CGHeroInstance * hero)
|
||||
backpackPos = 0;
|
||||
|
||||
// Fill the slots for worn artifacts and backpack.
|
||||
|
||||
|
||||
for(auto p : artWorn)
|
||||
{
|
||||
setSlotData(p.second, p.first);
|
||||
}
|
||||
|
||||
|
||||
scrollBackpack(0);
|
||||
}
|
||||
|
||||
@ -587,8 +566,8 @@ void CArtifactsOfHero::setSlotData(CArtPlace* artPlace, ArtifactPosition slotID)
|
||||
|
||||
if(const ArtSlotInfo *asi = curHero->getSlot(slotID))
|
||||
{
|
||||
artPlace->setArtifact(asi->artifact);
|
||||
artPlace->lockSlot(asi->locked);
|
||||
artPlace->setArtifact(asi->artifact);
|
||||
}
|
||||
else
|
||||
artPlace->setArtifact(nullptr);
|
||||
@ -615,7 +594,7 @@ CArtifactsOfHero::CArtifactsOfHero(std::map<ArtifactPosition, CArtPlace *> ArtWo
|
||||
{
|
||||
if(createCommonPart)
|
||||
{
|
||||
commonInfo = new CArtifactsOfHero::SCommonPart;
|
||||
commonInfo = std::make_shared<CArtifactsOfHero::SCommonPart>();
|
||||
commonInfo->participants.insert(this);
|
||||
}
|
||||
|
||||
@ -642,7 +621,7 @@ CArtifactsOfHero::CArtifactsOfHero(const Point& position, bool createCommonPart
|
||||
{
|
||||
if(createCommonPart)
|
||||
{
|
||||
commonInfo = new CArtifactsOfHero::SCommonPart;
|
||||
commonInfo = std::make_shared<CArtifactsOfHero::SCommonPart>();
|
||||
commonInfo->participants.insert(this);
|
||||
}
|
||||
|
||||
@ -797,7 +776,7 @@ void CArtifactsOfHero::artifactMoved(const ArtifactLocation &src, const Artifact
|
||||
}
|
||||
else if(src.slot >= GameConstants::BACKPACK_START &&
|
||||
src.slot < commonInfo->src.slotID &&
|
||||
src.isHolder(commonInfo->src.AOH->curHero)) //artifact taken from before currently picked one
|
||||
src.isHolder(commonInfo->src.AOH->curHero)) //artifact taken from before currently picked one
|
||||
{
|
||||
//int fixedSlot = src.hero->getArtPos(commonInfo->src.art);
|
||||
vstd::advance(commonInfo->src.slotID, -1);
|
||||
@ -811,14 +790,14 @@ void CArtifactsOfHero::artifactMoved(const ArtifactLocation &src, const Artifact
|
||||
}
|
||||
|
||||
updateParentWindow();
|
||||
int shift = 0;
|
||||
int shift = 0;
|
||||
// if(dst.slot >= Arts::BACKPACK_START && dst.slot - Arts::BACKPACK_START < backpackPos)
|
||||
// shift++;
|
||||
//
|
||||
if(src.slot < GameConstants::BACKPACK_START && dst.slot - GameConstants::BACKPACK_START < backpackPos)
|
||||
if(src.slot < GameConstants::BACKPACK_START && dst.slot - GameConstants::BACKPACK_START < backpackPos)
|
||||
shift++;
|
||||
if(dst.slot < GameConstants::BACKPACK_START && src.slot - GameConstants::BACKPACK_START < backpackPos)
|
||||
shift--;
|
||||
shift--;
|
||||
|
||||
if( (isCurHeroSrc && src.slot >= GameConstants::BACKPACK_START)
|
||||
|| (isCurHeroDst && dst.slot >= GameConstants::BACKPACK_START) )
|
||||
@ -853,7 +832,7 @@ CArtPlace * CArtifactsOfHero::getArtPlace(int slot)
|
||||
for(CArtPlace *ap : backpack)
|
||||
if(ap->slotID == slot)
|
||||
return ap;
|
||||
return nullptr;
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user