1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-12-24 22:14:36 +02:00

Move VievXXX logic to server side (except expert ViewEarth)

This commit is contained in:
AlexVinS 2015-02-26 17:15:17 +03:00
parent b6038240ab
commit f4c683cd5e
19 changed files with 263 additions and 112 deletions

View File

@ -530,6 +530,13 @@ void VCAI::showMarketWindow(const IMarket *market, const CGHeroInstance *visitor
NET_EVENT_HANDLER;
}
void VCAI::showWorldViewEx(const std::vector<ObjectPosInfo> & objectPositions)
{
//TODO: AI support for ViewXXX spell
LOG_TRACE(logAi);
NET_EVENT_HANDLER;
}
void VCAI::init(shared_ptr<CCallback> CB)
{
LOG_TRACE(logAi);

View File

@ -241,6 +241,7 @@ public:
virtual void buildChanged(const CGTownInstance *town, BuildingID buildingID, int what) override;
virtual void heroBonusChanged(const CGHeroInstance *hero, const Bonus &bonus, bool gain) override;
virtual void showMarketWindow(const IMarket *market, const CGHeroInstance *visitor) override;
void showWorldViewEx(const std::vector<ObjectPosInfo> & objectPositions) override;
virtual void battleStart(const CCreatureSet *army1, const CCreatureSet *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, bool side) override;
virtual void battleEnd(const BattleResult *br) override;

View File

@ -2189,25 +2189,11 @@ void CPlayerInterface::advmapSpellCast(const CGHeroInstance * caster, int spellI
}
const CSpell * spell = CGI->spellh->objects[spellID];
if(spellID == SpellID::VIEW_AIR)
if(spellID == SpellID::VIEW_EARTH)
{
//TODO: implement on server side
int level = caster->getSpellSchoolLevel(spell);
adventureInt->worldViewOptions.showAllArtifacts = true;
adventureInt->worldViewOptions.showAllHeroes = (level>1);
adventureInt->worldViewOptions.showAllTowns = (level>2);
viewWorldMap();
}
else if(spellID == SpellID::VIEW_EARTH)
{
int level = caster->getSpellSchoolLevel(spell);
adventureInt->worldViewOptions.showAllResources = true;
adventureInt->worldViewOptions.showAllMines = (level>1);
adventureInt->worldViewOptions.showAllTerrain = (level>2);
viewWorldMap();
}
auto castSoundPath = spell->getCastSound();
@ -2724,3 +2710,13 @@ void CPlayerInterface::doMoveHero(const CGHeroInstance* h, CGPath path)
duringMovement = false;
}
void CPlayerInterface::showWorldViewEx(const std::vector<ObjectPosInfo>& objectPositions)
{
EVENT_HANDLER_CALLED_BY_CLIENT;
//TODO: showWorldViewEx
std::copy(objectPositions.begin(), objectPositions.end(), std::back_inserter(adventureInt->worldViewOptions.iconPositions));
viewWorldMap();
}

View File

@ -196,6 +196,7 @@ public:
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;
//for battles
void actionFinished(const BattleAction& action) override;//occurs AFTER action taken by active stack or by the hero

View File

@ -834,6 +834,11 @@ void AdvmapSpellCast::applyCl(CClient *cl)
INTERFACE_CALL_IF_PRESENT(caster->getOwner(),advmapSpellCast, caster, spellID);
}
void ShowWorldViewEx::applyCl(CClient * cl)
{
CALL_ONLY_THAT_INTERFACE(player, showWorldViewEx, objectPositions);
}
void OpenWindow::applyCl(CClient *cl)
{
switch(window)

View File

@ -528,6 +528,40 @@ CMapHandler::CMapNormalBlitter::CMapNormalBlitter(CMapHandler * parent)
defaultTileRect = Rect(0, 0, tileSize, tileSize);
}
SDL_Surface * CMapHandler::CMapWorldViewBlitter::objectToIcon(Obj id, si32 subId, PlayerColor owner) const
{
int ownerIndex = 0;
if(owner < PlayerColor::PLAYER_LIMIT)
{
ownerIndex = owner.getNum() * 19;
}
else if (owner == PlayerColor::NEUTRAL)
{
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;
case Obj::SUBTERRANEAN_GATE:
return info->iconsDef->ourImages[(int)EWorldViewIcon::GATE].bitmap;
case Obj::ARTIFACT:
return info->iconsDef->ourImages[(int)EWorldViewIcon::ARTIFACT].bitmap;
case Obj::TOWN:
return info->iconsDef->ourImages[(int)EWorldViewIcon::TOWN + ownerIndex].bitmap;
case Obj::HERO:
return info->iconsDef->ourImages[(int)EWorldViewIcon::HERO + ownerIndex].bitmap;
case Obj::MINE:
return info->iconsDef->ourImages[(int)EWorldViewIcon::MINE_WOOD + subId + ownerIndex].bitmap;
case Obj::RESOURCE:
return info->iconsDef->ourImages[(int)EWorldViewIcon::RES_WOOD + subId + ownerIndex].bitmap;
}
return nullptr;
}
void CMapHandler::CMapWorldViewBlitter::calculateWorldViewCameraPos()
{
bool outsideLeft = topTile.x < 0;
@ -609,66 +643,56 @@ void CMapHandler::CMapWorldViewBlitter::drawElement(EMapCacheType cacheType, SDL
void CMapHandler::CMapWorldViewBlitter::drawTileOverlay(SDL_Surface * targetSurf, const TerrainTile2 & tile) const
{
auto drawIcon = [this,targetSurf](Obj id, si32 subId, PlayerColor owner)
{
SDL_Surface * wvIcon = this->objectToIcon(id, subId, 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);
}
};
auto & objects = tile.objects;
for(auto & object : objects)
{
const CGObjectInstance * obj = object.obj;
if (obj->pos.z != pos.z)
continue;
const bool sameLevel = obj->pos.z == pos.z;
const bool isVisible = (*info->visibilityMap)[pos.x][pos.y][pos.z];
if (!obj->visitableAt(pos.x, pos.y))
const bool isVisitable = obj->visitableAt(pos.x, pos.y);
if(sameLevel && isVisible && isVisitable)
drawIcon(obj->ID, obj->subID, obj->tempOwner);
}
}
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;
auto &ownerRaw = obj->tempOwner;
int ownerIndex = 0;
if (ownerRaw < PlayerColor::PLAYER_LIMIT)
{
ownerIndex = ownerRaw.getNum() * 19;
}
else if (ownerRaw == PlayerColor::NEUTRAL)
{
ownerIndex = PlayerColor::PLAYER_LIMIT.getNum() * 19;
}
SDL_Surface * wvIcon = nullptr;
switch (obj->ID)
{
default:
if((iconInfo.pos.x < topTile.x) || (iconInfo.pos.y < topTile.y))
continue;
case Obj::MONOLITH_ONE_WAY_ENTRANCE:
case Obj::MONOLITH_ONE_WAY_EXIT:
case Obj::MONOLITH_TWO_WAY:
if(isVisible)
wvIcon = info->iconsDef->ourImages[(int)EWorldViewIcon::TELEPORT].bitmap;
break;
case Obj::SUBTERRANEAN_GATE:
if(isVisible)
wvIcon = info->iconsDef->ourImages[(int)EWorldViewIcon::GATE].bitmap;
break;
case Obj::ARTIFACT:
if(isVisible || info->showAllArtifacts)
wvIcon = info->iconsDef->ourImages[(int)EWorldViewIcon::ARTIFACT].bitmap;
break;
case Obj::TOWN:
if(isVisible || info->showAllTowns)
wvIcon = info->iconsDef->ourImages[(int)EWorldViewIcon::TOWN + ownerIndex].bitmap;
break;
case Obj::HERO:
if(isVisible || info->showAllHeroes)
wvIcon = info->iconsDef->ourImages[(int)EWorldViewIcon::HERO + ownerIndex].bitmap;
break;
case Obj::MINE:
if(isVisible || info->showAllMines)
wvIcon = info->iconsDef->ourImages[(int)EWorldViewIcon::MINE_WOOD + obj->subID + ownerIndex].bitmap;
break;
case Obj::RESOURCE:
if(isVisible || info->showAllResources)
wvIcon = info->iconsDef->ourImages[(int)EWorldViewIcon::RES_WOOD + obj->subID + ownerIndex].bitmap;
break;
}
if (wvIcon)
if((iconInfo.pos.x > bottomRight.x) || (iconInfo.pos.y > bottomRight.y))
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)
{
// 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);
@ -791,6 +815,11 @@ void CMapHandler::CMapBlitter::drawFrame(SDL_Surface * targetSurf) const
drawElement(EMapCacheType::FRAME, parent->ttiles[pos.x][pos.y][topTile.z].terbitmap, nullptr, targetSurf, &destRect);
}
void CMapHandler::CMapBlitter::drawOverlayEx(SDL_Surface * targetSurf)
{
//nothing to do here
}
void CMapHandler::CMapBlitter::drawHeroFlag(SDL_Surface * targetSurf, SDL_Surface * sourceSurf, SDL_Rect * sourceRect, SDL_Rect * destRect, bool moving) const
{
drawElement(EMapCacheType::HERO_FLAGS, sourceSurf, sourceRect, targetSurf, destRect, false);
@ -982,6 +1011,8 @@ void CMapHandler::CMapBlitter::blit(SDL_Surface * targetSurf, const MapDrawingIn
}
}
drawOverlayEx(targetSurf);
// drawDebugGrid()
if (settings["session"]["showGrid"].Bool())
{

View File

@ -2,6 +2,7 @@
#include "../lib/int3.h"
#include "../lib/spells/ViewSpellInt.h"
#include "gui/Geometries.h"
#include "SDL.h"
@ -101,13 +102,8 @@ struct MapDrawingInfo
bool puzzleMode;
int3 grailPos; // location of grail for puzzle mode [in tiles]
const std::vector<ObjectPosInfo> * additionalIcons;
bool showAllArtifacts; //for basic viewAir
bool showAllHeroes; //for advanced viewAir
bool showAllTowns; //for expert viewAir
bool showAllResources; //for basic viewEarth
bool showAllMines; //for advanced viewEarth
bool showAllTerrain; //for expert viewEarth
MapDrawingInfo(int3 &topTile_, const std::vector< std::vector< std::vector<ui8> > > * visibilityMap_, SDL_Rect * drawBounds_, CDefHandler * iconsDef_ = nullptr)
@ -123,11 +119,7 @@ struct MapDrawingInfo
movement(int3()),
puzzleMode(false),
grailPos(int3()),
showAllArtifacts(false),
showAllHeroes(false),
showAllTowns(false),
showAllResources(false),
showAllMines(false),
additionalIcons(nullptr),
showAllTerrain(false)
{}
@ -253,6 +245,8 @@ class CMapHandler
virtual void drawFow(SDL_Surface * targetSurf) const;
/// draws map border frame on current position
virtual void drawFrame(SDL_Surface * targetSurf) const;
/// draws additional icons (for VIEW_AIR, VIEW_EARTH spells atm)
virtual void drawOverlayEx(SDL_Surface * targetSurf);
// third drawing pass
@ -308,6 +302,8 @@ class CMapHandler
class CMapWorldViewBlitter : public CMapBlitter
{
private:
SDL_Surface * 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;
@ -316,6 +312,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 init(const MapDrawingInfo * info) override;
SDL_Rect clip(SDL_Surface * targetSurf) const override;

View File

@ -1854,16 +1854,15 @@ CAdvMapInt::WorldViewOptions::WorldViewOptions()
void CAdvMapInt::WorldViewOptions::clear()
{
showAllArtifacts = showAllHeroes = showAllTowns = showAllResources = showAllMines = showAllTerrain = false;
showAllTerrain = false;
iconPositions.clear();
}
void CAdvMapInt::WorldViewOptions::adjustDrawingInfo(MapDrawingInfo& info)
{
info.showAllArtifacts = showAllArtifacts;
info.showAllHeroes = showAllHeroes;
info.showAllTowns = showAllTowns;
info.showAllResources = showAllResources;
info.showAllMines = showAllMines;
info.showAllTerrain = showAllTerrain;
info.additionalIcons = &iconPositions;
}

View File

@ -6,6 +6,8 @@
#include "../widgets/TextControls.h"
#include "../widgets/Buttons.h"
#include "../../lib/spells/ViewSpellInt.h"
class CDefHandler;
class CCallback;
struct CGPath;
@ -131,14 +133,10 @@ public:
struct WorldViewOptions
{
bool showAllArtifacts; //for basic viewAir
bool showAllHeroes; //for advanced viewAir
bool showAllTowns; //for expert viewAir
bool showAllResources; //for basic viewEarth
bool showAllMines; //for advanced viewEarth
bool showAllTerrain; //for expert viewEarth
std::vector<ObjectPosInfo> iconPositions;
WorldViewOptions();
void clear();

View File

@ -5,6 +5,8 @@
#include "IGameEventsReceiver.h"
#include "CGameStateFwd.h"
#include "spells/ViewSpellInt.h"
/*
* CGameInterface.h, part of VCMI engine
*
@ -93,6 +95,8 @@ public:
// all stacks operations between these objects become allowed, interface has to call onEnd when done
virtual void showGarrisonDialog(const CArmedInstance *up, const CGHeroInstance *down, bool removableUnits, QueryID queryID) = 0;
virtual void finish(){}; //if for some reason we want to end
virtual void showWorldViewEx(const std::vector<ObjectPosInfo> & objectPositions){};
};
class DLL_LINKAGE CDynLibHandler

View File

@ -60,6 +60,7 @@ set(lib_SRCS
spells/BattleSpellMechanics.cpp
spells/CreatureSpellMechanics.cpp
spells/CDefaultSpellMechanics.cpp
spells/ViewSpellInt.cpp
BattleAction.cpp
BattleHex.cpp

View File

@ -16,6 +16,8 @@
#include "mapping/CMap.h"
#include "CObstacleInstance.h"
#include "spells/ViewSpellInt.h"
/*
* NetPacks.h, part of VCMI engine
*
@ -1685,6 +1687,22 @@ struct AdvmapSpellCast : public CPackForClient //108
}
};
struct ShowWorldViewEx : public CPackForClient //4000
{
PlayerColor player;
std::vector<ObjectPosInfo> objectPositions;
ShowWorldViewEx(){type = 4000;}
void applyCl(CClient *cl);
template <typename Handler> void serialize(Handler &h, const int version)
{
h & player & objectPositions;
}
};
/***********************************************************************************************************/
struct CommitPackage : public CPackForServer

View File

@ -302,6 +302,8 @@
<Unit filename="spells/CreatureSpellMechanics.h" />
<Unit filename="spells/ISpellMechanics.cpp" />
<Unit filename="spells/ISpellMechanics.h" />
<Unit filename="spells/ViewSpellInt.cpp" />
<Unit filename="spells/ViewSpellInt.h" />
<Unit filename="vcmi_endian.h" />
<Extensions>
<code_completion />

View File

@ -193,6 +193,7 @@
<ClCompile Include="spells\BattleSpellMechanics.cpp" />
<ClCompile Include="spells\CreatureSpellMechanics.cpp" />
<ClCompile Include="spells\CDefaultSpellMechanics.cpp" />
<ClCompile Include="spells\ViewSpellInt.cpp" />
<ClCompile Include="filesystem\AdapterLoaders.cpp" />
<ClCompile Include="filesystem\CArchiveLoader.cpp" />
<ClCompile Include="filesystem\CBinaryReader.cpp" />

View File

@ -248,6 +248,7 @@ void registerTypesClientPacks1(Serializer &s)
s.template registerType<CPackForClient, HeroVisit>();
s.template registerType<CPackForClient, SetCommanderProperty>();
s.template registerType<CPackForClient, ChangeObjectVisitors>();
s.template registerType<CPackForClient, ShowWorldViewEx>();
}
template<typename Serializer>

View File

@ -240,13 +240,34 @@ bool TownPortalMechanics::applyAdventureEffects(const SpellCastEnvironment * env
return true;
}
bool ViewAirMechanics::applyAdventureEffects(const SpellCastEnvironment* env, AdventureSpellCastParameters& parameters) const
bool ViewMechanics::applyAdventureEffects(const SpellCastEnvironment * env, AdventureSpellCastParameters & parameters) const
{
return true; //implemented on client side
ShowWorldViewEx pack;
pack.player = parameters.caster->tempOwner;
const int spellLevel = parameters.caster->getSpellSchoolLevel(owner);
for(const CGObjectInstance * obj : env->getMap()->objects)
{
//we need to send only not visible objects
if(filterObject(obj, spellLevel))
pack.objectPositions.push_back(ObjectPosInfo(obj));
}
env->sendAndApply(&pack);
return true;
}
bool ViewEarthMechanics::applyAdventureEffects(const SpellCastEnvironment* env, AdventureSpellCastParameters& parameters) const
bool ViewAirMechanics::filterObject(const CGObjectInstance * obj, const int spellLevel) const
{
return true; //implemented on client side
return (obj->ID == Obj::ARTIFACT) || (spellLevel>1 && obj->ID == Obj::HERO) || (spellLevel>2 && obj->ID == Obj::TOWN);
}
bool ViewEarthMechanics::filterObject(const CGObjectInstance * obj, const int spellLevel) const
{
return (obj->ID == Obj::RESOURCE) || (spellLevel>1 && obj->ID == Obj::MINE);
}

View File

@ -45,20 +45,29 @@ protected:
bool applyAdventureEffects(const SpellCastEnvironment * env, AdventureSpellCastParameters & parameters) const override;
};
class ViewAirMechanics: public DefaultSpellMechanics
class ViewMechanics: public DefaultSpellMechanics
{
public:
ViewAirMechanics(CSpell * s): DefaultSpellMechanics(s){};
ViewMechanics(CSpell * s): DefaultSpellMechanics(s){};
protected:
bool applyAdventureEffects(const SpellCastEnvironment * env, AdventureSpellCastParameters & parameters) const override;
virtual bool filterObject(const CGObjectInstance * obj, const int spellLevel) const = 0;
};
class ViewEarthMechanics: public DefaultSpellMechanics
class ViewAirMechanics: public ViewMechanics
{
public:
ViewEarthMechanics(CSpell * s): DefaultSpellMechanics(s){};
ViewAirMechanics(CSpell * s): ViewMechanics(s){};
protected:
bool applyAdventureEffects(const SpellCastEnvironment * env, AdventureSpellCastParameters & parameters) const override;
bool filterObject(const CGObjectInstance * obj, const int spellLevel) const override;
};
class ViewEarthMechanics: public ViewMechanics
{
public:
ViewEarthMechanics(CSpell * s): ViewMechanics(s){};
protected:
bool filterObject(const CGObjectInstance * obj, const int spellLevel) const override;
};

View File

@ -0,0 +1,27 @@
/*
* ViewSpellInt.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 "ViewSpellInt.h"
#include "../mapObjects/CObjectHandler.h"
ObjectPosInfo::ObjectPosInfo():
pos(),id(Obj::NO_OBJ), subId(-1), owner(PlayerColor::CANNOT_DETERMINE)
{
}
ObjectPosInfo::ObjectPosInfo(const CGObjectInstance * obj):
pos(obj->pos),id(obj->ID), subId(obj->subID), owner(obj->tempOwner)
{
}

32
lib/spells/ViewSpellInt.h Normal file
View File

@ -0,0 +1,32 @@
/*
* ViewSpellInt.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
*
*/
#pragma once
#include "../int3.h"
#include "../GameConstants.h"
class CGObjectInstance;
struct DLL_LINKAGE ObjectPosInfo
{
int3 pos;
Obj id;
si32 subId;
PlayerColor owner;
ObjectPosInfo();
ObjectPosInfo(const CGObjectInstance * obj);
template <typename Handler> void serialize(Handler &h, const int version)
{
h & pos & id & subId & owner;
}
};