mirror of
https://github.com/edubart/otclient.git
synced 2025-12-02 16:06:51 +01:00
Just rename some files
* Fix a server ping issue
This commit is contained in:
100
src/client/CMakeLists.txt
Normal file
100
src/client/CMakeLists.txt
Normal file
@@ -0,0 +1,100 @@
|
||||
# CMAKE_CURRENT_LIST_DIR cmake 2.6 compatibility
|
||||
if(${CMAKE_MAJOR_VERSION} EQUAL 2 AND ${CMAKE_MINOR_VERSION} EQUAL 6)
|
||||
get_filename_component(CMAKE_CURRENT_LIST_DIR ${CMAKE_CURRENT_LIST_FILE} PATH)
|
||||
endif(${CMAKE_MAJOR_VERSION} EQUAL 2 AND ${CMAKE_MINOR_VERSION} EQUAL 6)
|
||||
|
||||
# client options
|
||||
add_definitions(-DOTCLIENT)
|
||||
option(BOT_PROTECTION "Enable bot protection" ON)
|
||||
if(BOT_PROTECTION)
|
||||
add_definitions(-DBOT_PROTECTION)
|
||||
message(STATUS "Bot protection: ON")
|
||||
else(BOT_PROTECTION)
|
||||
message(STATUS "Bot protection: OFF")
|
||||
endif(BOT_PROTECTION)
|
||||
|
||||
set(client_SOURCES ${client_SOURCES}
|
||||
# client
|
||||
${CMAKE_CURRENT_LIST_DIR}/const.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/global.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/luafunctions.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/client.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/client.h
|
||||
|
||||
# core
|
||||
${CMAKE_CURRENT_LIST_DIR}/animatedtext.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/animatedtext.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/container.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/container.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/creature.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/creature.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/declarations.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/effect.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/effect.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/game.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/game.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/shadermanager.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/shadermanager.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/item.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/item.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/localplayer.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/localplayer.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/map.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/map.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/mapio.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/mapview.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/mapview.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/lightview.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/lightview.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/missile.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/missile.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/outfit.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/outfit.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/player.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/player.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/spritemanager.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/spritemanager.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/statictext.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/statictext.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/thing.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/thing.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/thingtypemanager.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/thingtypemanager.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/thingtype.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/thingtype.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/itemtype.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/itemtype.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/tile.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/tile.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/houses.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/houses.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/towns.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/towns.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/creatures.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/creatures.h
|
||||
|
||||
# lua
|
||||
${CMAKE_CURRENT_LIST_DIR}/luavaluecasts.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/luavaluecasts.h
|
||||
|
||||
# net
|
||||
${CMAKE_CURRENT_LIST_DIR}/protocolcodes.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/protocolcodes.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/protocolgame.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/protocolgame.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/protocolgameparse.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/protocolgamesend.cpp
|
||||
|
||||
# ui
|
||||
${CMAKE_CURRENT_LIST_DIR}/uicreature.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/uicreature.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/uiitem.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/uiitem.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/uimap.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/uimap.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/uiprogressrect.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/uiprogressrect.h
|
||||
|
||||
# util
|
||||
${CMAKE_CURRENT_LIST_DIR}/position.h
|
||||
)
|
||||
67
src/client/animatedtext.cpp
Normal file
67
src/client/animatedtext.cpp
Normal file
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Copyright (c) 2010-2013 OTClient <https://github.com/edubart/otclient>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "animatedtext.h"
|
||||
#include "map.h"
|
||||
#include <framework/core/clock.h>
|
||||
#include <framework/core/eventdispatcher.h>
|
||||
#include <framework/graphics/graphics.h>
|
||||
|
||||
AnimatedText::AnimatedText()
|
||||
{
|
||||
m_cachedText.setFont(g_fonts.getFont("verdana-11px-rounded"));
|
||||
m_cachedText.setAlign(Fw::AlignLeft);
|
||||
}
|
||||
|
||||
void AnimatedText::drawText(const Point& dest, const Rect& visibleRect)
|
||||
{
|
||||
Point p = dest;
|
||||
Size textSize = m_cachedText.getTextSize();
|
||||
p.x += 20 - textSize.width() / 2;
|
||||
p.y += (-20 * m_animationTimer.ticksElapsed()) / Otc::ANIMATED_TEXT_DURATION;
|
||||
Rect rect(p, textSize);
|
||||
|
||||
if(visibleRect.contains(rect)) {
|
||||
//TODO: cache into a framebuffer
|
||||
g_painter->setColor(m_color);
|
||||
m_cachedText.draw(rect);
|
||||
}
|
||||
}
|
||||
|
||||
void AnimatedText::onAppear()
|
||||
{
|
||||
m_animationTimer.restart();
|
||||
|
||||
// schedule removal
|
||||
auto self = asAnimatedText();
|
||||
g_dispatcher.scheduleEvent([self]() { g_map.removeThing(self); }, Otc::ANIMATED_TEXT_DURATION);
|
||||
}
|
||||
|
||||
void AnimatedText::setColor(int color)
|
||||
{
|
||||
m_color = Color::from8bit(color);
|
||||
}
|
||||
|
||||
void AnimatedText::setText(const std::string& text)
|
||||
{
|
||||
m_cachedText.setText(text);
|
||||
}
|
||||
54
src/client/animatedtext.h
Normal file
54
src/client/animatedtext.h
Normal file
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright (c) 2010-2013 OTClient <https://github.com/edubart/otclient>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef ANIMATEDTEXT_H
|
||||
#define ANIMATEDTEXT_H
|
||||
|
||||
#include "thing.h"
|
||||
#include <framework/graphics/fontmanager.h>
|
||||
#include <framework/core/timer.h>
|
||||
#include <framework/graphics/cachedtext.h>
|
||||
|
||||
// @bindclass
|
||||
class AnimatedText : public Thing
|
||||
{
|
||||
public:
|
||||
AnimatedText();
|
||||
|
||||
void drawText(const Point& dest, const Rect& visibleRect);
|
||||
|
||||
void setColor(int color);
|
||||
void setText(const std::string& text);
|
||||
|
||||
AnimatedTextPtr asAnimatedText() { return static_self_cast<AnimatedText>(); }
|
||||
bool isAnimatedText() { return true; }
|
||||
|
||||
protected:
|
||||
virtual void onAppear();
|
||||
|
||||
private:
|
||||
Color m_color;
|
||||
Timer m_animationTimer;
|
||||
CachedText m_cachedText;
|
||||
};
|
||||
|
||||
#endif
|
||||
89
src/client/client.cpp
Normal file
89
src/client/client.cpp
Normal file
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* Copyright (c) 2010-2013 OTClient <https://github.com/edubart/otclient>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "client.h"
|
||||
#include <framework/core/modulemanager.h>
|
||||
#include <framework/core/resourcemanager.h>
|
||||
#include <framework/graphics/graphics.h>
|
||||
#include "game.h"
|
||||
#include "map.h"
|
||||
#include "shadermanager.h"
|
||||
#include "spritemanager.h"
|
||||
#include <framework/core/configmanager.h>
|
||||
|
||||
Client g_client;
|
||||
|
||||
void Client::init(std::vector<std::string>& args)
|
||||
{
|
||||
// register needed lua functions
|
||||
registerLuaFunctions();
|
||||
|
||||
g_game.init();
|
||||
g_shaders.init();
|
||||
g_things.init();
|
||||
|
||||
//TODO: restore options
|
||||
/*
|
||||
if(g_graphics.parseOption(arg))
|
||||
continue;
|
||||
|
||||
if(arg == "-version" || arg == "--version" || arg == "-v") {
|
||||
stdext::print(
|
||||
m_appName, " ", m_appVersion, "\n"
|
||||
"Buitt on: ", BUILD_DATE, "\n",
|
||||
"Commit: ", BUILD_COMMIT, "\n",
|
||||
"Compiled by: ", BUILD_COMPILER, "\n",
|
||||
"Build type: ", BUILD_TYPE, "\n");
|
||||
return;
|
||||
} else if(arg == "-help" || arg == "--help" || arg == "-h" || arg == "-?" || arg == "/?") {
|
||||
stdext::print(
|
||||
"Usage: ", args[0], " [options]\n"
|
||||
"Options:\n"
|
||||
" -help Display this information and exit\n"
|
||||
" -version Display version and exit\n"
|
||||
" \n"
|
||||
" -no-fbos Disable usage of opengl framebuffer objects\n"
|
||||
" -no-mipmaps Disable texture mipmaping\n"
|
||||
" -no-smooth Disable texture smoothing (bilinear filter)\n"
|
||||
" -no-non-power-of-two-textures Use only power of two textures\n"
|
||||
" -no-clamp-to-edge Don't use GL_CLAMP_TO_EDGE\n"
|
||||
" -no-backbuffer-cache Don't allow backbuffer caching\n"
|
||||
" -hardware-buffers Cache vertex arrays in hardware\n"
|
||||
" -opengl1 Use OpenGL 1.x painter\n"
|
||||
" -opengl2 Use OpenGL 2.0 painter\n");
|
||||
return;
|
||||
} else {
|
||||
stdext::println("Unrecognized option '", arg, "', please see -help for available options list");
|
||||
return;
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
void Client::terminate()
|
||||
{
|
||||
g_creatures.terminate();
|
||||
g_game.terminate();
|
||||
g_map.terminate();
|
||||
g_things.terminate();
|
||||
g_sprites.terminate();
|
||||
g_shaders.terminate();
|
||||
}
|
||||
38
src/client/client.h
Normal file
38
src/client/client.h
Normal file
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright (c) 2010-2013 OTClient <https://github.com/edubart/otclient>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef CLIENT_H
|
||||
#define CLIENT_H
|
||||
|
||||
#include "global.h"
|
||||
|
||||
class Client
|
||||
{
|
||||
public:
|
||||
void init(std::vector<std::string>& args);
|
||||
void terminate();
|
||||
void registerLuaFunctions();
|
||||
};
|
||||
|
||||
extern Client g_client;
|
||||
|
||||
#endif
|
||||
408
src/client/const.h
Normal file
408
src/client/const.h
Normal file
@@ -0,0 +1,408 @@
|
||||
/*
|
||||
* Copyright (c) 2010-2013 OTClient <https://github.com/edubart/otclient>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef OTCLIENT_CONST_H
|
||||
#define OTCLIENT_CONST_H
|
||||
|
||||
namespace Otc
|
||||
{
|
||||
enum {
|
||||
TILE_PIXELS = 32,
|
||||
MAX_ELEVATION = 24,
|
||||
|
||||
SEA_FLOOR = 7,
|
||||
MAX_Z = 15,
|
||||
UNDERGROUND_FLOOR = SEA_FLOOR+1,
|
||||
VISIBLE_X_TILES = 15,
|
||||
VISIBLE_Y_TILES = 11,
|
||||
AWARE_UNDEGROUND_FLOOR_RANGE = 2,
|
||||
AWARE_X_TILES = VISIBLE_X_TILES + 3,
|
||||
AWARE_Y_TILES = VISIBLE_Y_TILES + 3,
|
||||
AWARE_X_LEFT_TILES = AWARE_X_TILES/2 - 1,
|
||||
AWARE_X_RIGHT_TILES = AWARE_X_TILES/2,
|
||||
AWARE_Y_TOP_TILES = AWARE_Y_TILES/2 - 1,
|
||||
AWARE_Y_BOTTOM_TILES = AWARE_Y_TILES/2,
|
||||
|
||||
INVISIBLE_TICKS_PER_FRAME = 500,
|
||||
ITEM_TICKS_PER_FRAME = 500,
|
||||
ANIMATED_TEXT_DURATION = 1000,
|
||||
STATIC_DURATION_PER_CHARACTER = 60,
|
||||
MIN_STATIC_TEXT_DURATION = 3000,
|
||||
MAX_STATIC_TEXT_WIDTH = 200,
|
||||
MAX_AUTOWALK_STEPS_RETRY = 10
|
||||
};
|
||||
|
||||
enum DrawFlags {
|
||||
DrawGround = 1,
|
||||
DrawGroundBorders = 2,
|
||||
DrawOnBottom = 4,
|
||||
DrawOnTop = 8,
|
||||
DrawItems = 16,
|
||||
DrawCreatures = 32,
|
||||
DrawEffects = 64,
|
||||
DrawMissiles = 128,
|
||||
DrawCreaturesInformation = 256,
|
||||
DrawStaticTexts = 512,
|
||||
DrawAnimatedTexts = 1024,
|
||||
DrawAnimations = 2048,
|
||||
DrawWalls = DrawOnBottom | DrawOnTop,
|
||||
DrawEverything = DrawGround | DrawGroundBorders | DrawWalls | DrawItems |
|
||||
DrawCreatures | DrawEffects | DrawMissiles | DrawCreaturesInformation |
|
||||
DrawStaticTexts | DrawAnimatedTexts | DrawAnimations
|
||||
};
|
||||
|
||||
enum DatOpts {
|
||||
DatGround = 0,
|
||||
DatGroundClip,
|
||||
DatOnBottom,
|
||||
DatOnTop,
|
||||
DatContainer,
|
||||
DatStackable,
|
||||
DatForceUse,
|
||||
DatMultiUse,
|
||||
DatWritable,
|
||||
DatWritableOnce,
|
||||
DatFluidContainer,
|
||||
DatSplash,
|
||||
DatBlockWalk,
|
||||
DatNotMoveable,
|
||||
DatBlockProjectile,
|
||||
DatBlockPathFind,
|
||||
DatPickupable,
|
||||
DatHangable,
|
||||
DatHookSouth,
|
||||
DatHookEast,
|
||||
DatRotable,
|
||||
DatLight,
|
||||
DatDontHide,
|
||||
DatTranslucent,
|
||||
DatDisplacement,
|
||||
DatElevation,
|
||||
DatLyingCorpse,
|
||||
DatAnimateAlways,
|
||||
DatMinimapColor,
|
||||
DatLensHelp,
|
||||
DatFullGround,
|
||||
DatIgnoreLook,
|
||||
DatCloth,
|
||||
DatAnimation, // lastest tibia
|
||||
DatLastOpt = 255
|
||||
};
|
||||
|
||||
enum InventorySlot {
|
||||
InventorySlotHead = 1,
|
||||
InventorySlotNecklace,
|
||||
InventorySlotBackpack,
|
||||
InventorySlotArmor,
|
||||
InventorySlotRight,
|
||||
InventorySlotLeft,
|
||||
InventorySlotLegs,
|
||||
InventorySlotFeet,
|
||||
InventorySlotRing,
|
||||
InventorySlotAmmo,
|
||||
InventorySlotPurse,
|
||||
InventorySlotExt1,
|
||||
InventorySlotExt2,
|
||||
InventorySlotExt3,
|
||||
InventorySlotExt4,
|
||||
LastInventorySlot
|
||||
};
|
||||
|
||||
enum Statistic {
|
||||
Health = 0,
|
||||
MaxHealth,
|
||||
FreeCapacity,
|
||||
Experience,
|
||||
Level,
|
||||
LevelPercent,
|
||||
Mana,
|
||||
MaxMana,
|
||||
MagicLevel,
|
||||
MagicLevelPercent,
|
||||
Soul,
|
||||
Stamina,
|
||||
LastStatistic
|
||||
};
|
||||
|
||||
enum Skill {
|
||||
Fist = 0,
|
||||
Club,
|
||||
Sword,
|
||||
Axe,
|
||||
Distance,
|
||||
Shielding,
|
||||
Fishing,
|
||||
LastSkill
|
||||
};
|
||||
|
||||
enum Direction {
|
||||
North = 0,
|
||||
East,
|
||||
South,
|
||||
West,
|
||||
NorthEast,
|
||||
SouthEast,
|
||||
SouthWest,
|
||||
NorthWest,
|
||||
InvalidDirection
|
||||
};
|
||||
|
||||
enum FluidsColor {
|
||||
FluidTransparent = 0,
|
||||
FluidBlue,
|
||||
FluidRed,
|
||||
FluidBrown,
|
||||
FluidGreen,
|
||||
FluidYellow,
|
||||
FluidWhite,
|
||||
FluidPurple
|
||||
};
|
||||
|
||||
enum FluidsType {
|
||||
FluidNone = 0,
|
||||
FluidWater,
|
||||
FluidMana,
|
||||
FluidBeer,
|
||||
FluidOil,
|
||||
FluidBlood,
|
||||
FluidSlime,
|
||||
FluidMud,
|
||||
FluidLemonade,
|
||||
FluidMilk,
|
||||
FluidWine,
|
||||
FluidHealth,
|
||||
FluidUrine,
|
||||
FluidRum,
|
||||
FluidFruidJuice,
|
||||
FluidCoconutMilk,
|
||||
FluidTea,
|
||||
FluidMead
|
||||
};
|
||||
|
||||
enum FightModes {
|
||||
FightOffensive = 1,
|
||||
FightBalanced = 2,
|
||||
FightDefensive = 3
|
||||
};
|
||||
|
||||
enum ChaseModes {
|
||||
DontChase = 0,
|
||||
ChaseOpponent = 1
|
||||
};
|
||||
|
||||
enum PlayerSkulls {
|
||||
SkullNone = 0,
|
||||
SkullYellow,
|
||||
SkullGreen,
|
||||
SkullWhite,
|
||||
SkullRed,
|
||||
SkullBlack,
|
||||
SkullOrange
|
||||
};
|
||||
|
||||
enum PlayerShields {
|
||||
ShieldNone = 0,
|
||||
ShieldWhiteYellow, // 1 party leader
|
||||
ShieldWhiteBlue, // 2 party member
|
||||
ShieldBlue, // 3 party member sexp off
|
||||
ShieldYellow, // 4 party leader sexp off
|
||||
ShieldBlueSharedExp, // 5 party member sexp on
|
||||
ShieldYellowSharedExp, // 6 // party leader sexp on
|
||||
ShieldBlueNoSharedExpBlink, // 7 party member sexp inactive guilty
|
||||
ShieldYellowNoSharedExpBlink, // 8 // party leader sexp inactive guilty
|
||||
ShieldBlueNoSharedExp, // 9 party member sexp inactive innocent
|
||||
ShieldYellowNoSharedExp // 10 party leader sexp inactive innocent
|
||||
};
|
||||
|
||||
enum PlayerEmblems {
|
||||
EmblemNone = 0,
|
||||
EmblemGreen,
|
||||
EmblemRed,
|
||||
EmblemBlue
|
||||
};
|
||||
|
||||
enum PlayerStates {
|
||||
IconNone = 0,
|
||||
IconPoison = 1,
|
||||
IconBurn = 2,
|
||||
IconEnergy = 4,
|
||||
IconDrunk = 8,
|
||||
IconManaShield = 16,
|
||||
IconParalyze = 32,
|
||||
IconHaste = 64,
|
||||
IconSwords = 128,
|
||||
IconDrowning = 256,
|
||||
IconFreezing = 512,
|
||||
IconDazzled = 1024,
|
||||
IconCursed = 2048,
|
||||
IconPartyBuff = 4096,
|
||||
IconPzBlock = 8192,
|
||||
IconPz = 16384,
|
||||
IconBleeding = 32768,
|
||||
IconHungry = 65536
|
||||
};
|
||||
|
||||
enum MessageMode {
|
||||
MessageNone = 0,
|
||||
MessageSay = 1,
|
||||
MessageWhisper = 2,
|
||||
MessageYell = 3,
|
||||
MessagePrivateFrom = 4,
|
||||
MessagePrivateTo = 5,
|
||||
MessageChannelManagement = 6,
|
||||
MessageChannel = 7,
|
||||
MessageChannelHighlight = 8,
|
||||
MessageSpell = 9,
|
||||
MessageNpcFrom = 10,
|
||||
MessageNpcTo = 11,
|
||||
MessageGamemasterBroadcast = 12,
|
||||
MessageGamemasterChannel = 13,
|
||||
MessageGamemasterPrivateFrom = 14,
|
||||
MessageGamemasterPrivateTo = 15,
|
||||
MessageLogin = 16,
|
||||
MessageWarning = 17,
|
||||
MessageGame = 18,
|
||||
MessageFailure = 19,
|
||||
MessageLook = 20,
|
||||
MessageDamageDealed = 21,
|
||||
MessageDamageReceived = 22,
|
||||
MessageHeal = 23,
|
||||
MessageExp = 24,
|
||||
MessageDamageOthers = 25,
|
||||
MessageHealOthers = 26,
|
||||
MessageExpOthers = 27,
|
||||
MessageStatus = 28,
|
||||
MessageLoot = 29,
|
||||
MessageTradeNpc = 30,
|
||||
MessageGuild = 31,
|
||||
MessagePartyManagement = 32,
|
||||
MessageParty = 33,
|
||||
MessageBarkLow = 34,
|
||||
MessageBarkLoud = 35,
|
||||
MessageReport = 36,
|
||||
MessageHotkeyUse = 37,
|
||||
MessageTutorialHint = 38,
|
||||
MessageThankyou = 39,
|
||||
MessageMarket = 40,
|
||||
MessageBeyondLast = 41,
|
||||
|
||||
// deprecated
|
||||
MessageMonsterYell = 42,
|
||||
MessageMonsterSay = 43,
|
||||
MessageRed = 44,
|
||||
MessageBlue = 45,
|
||||
MessageRVRChannel = 46,
|
||||
MessageRVRAnswer = 47,
|
||||
MessageRVRContinue = 48,
|
||||
LastMessage = 49,
|
||||
MessageInvalid = 255
|
||||
};
|
||||
|
||||
enum GameFeature {
|
||||
// 1-50 defined in c++
|
||||
GameProtocolChecksum = 1,
|
||||
GameAccountNames = 2,
|
||||
GameChallangeOnLogin = 3,
|
||||
GamePenalityOnDeath = 4,
|
||||
GameNameOnNpcTrade = 5,
|
||||
GameDoubleFreeCapacity = 6,
|
||||
GameDoubleExperience = 7,
|
||||
GameTotalCapacity = 8,
|
||||
GameSkillsBase = 9,
|
||||
GamePlayerRegenerationTime = 10,
|
||||
GameChannelPlayerList = 11,
|
||||
GamePlayerMounts = 12,
|
||||
GameEnvironmentEffect = 13,
|
||||
GameCreatureEmblems = 14,
|
||||
GameItemAnimationPhase = 15,
|
||||
GameMagicEffectU16 = 16,
|
||||
GamePlayerMarket = 17,
|
||||
GameSpritesU32 = 18,
|
||||
GameChargeableItems = 19,
|
||||
GameOfflineTrainingTime = 20,
|
||||
GamePurseSlot = 21,
|
||||
GameFormatCreatureName = 22,
|
||||
GameSpellList = 23,
|
||||
GameClientPing = 24,
|
||||
GameLoginPending = 25,
|
||||
GameNewSpeedLaw = 26,
|
||||
// 23-50 unused yet
|
||||
// 51-100 reserved to be defined in lua
|
||||
LastGameFeature = 101
|
||||
};
|
||||
|
||||
enum PathFindResult {
|
||||
PathFindResultOk = 0,
|
||||
PathFindResultSamePosition,
|
||||
PathFindResultImpossible,
|
||||
PathFindResultTooFar,
|
||||
PathFindResultNoWay
|
||||
};
|
||||
|
||||
enum PathFindFlags {
|
||||
PathFindAllowNullTiles = 1,
|
||||
PathFindAllowCreatures = 2,
|
||||
PathFindAllowNonPathable = 4,
|
||||
PathFindAllowNonWalkable = 8
|
||||
};
|
||||
|
||||
enum AutomapFlags
|
||||
{
|
||||
MapMarkTick = 0,
|
||||
MapMarkQuestion,
|
||||
MapMarkExclamation,
|
||||
MapMarkStar,
|
||||
MapMarkCross,
|
||||
MapMarkTemple,
|
||||
MapMarkKiss,
|
||||
MapMarkShovel,
|
||||
MapMarkSword,
|
||||
MapMarkFlag,
|
||||
MapMarkLock,
|
||||
MapMarkBag,
|
||||
MapMarkSkull,
|
||||
MapMarkDollar,
|
||||
MapMarkRedNorth,
|
||||
MapMarkRedSouth,
|
||||
MapMarkRedEast,
|
||||
MapMarkRedWest,
|
||||
MapMarkGreenNorth,
|
||||
MapMarkGreenSouth
|
||||
};
|
||||
|
||||
enum VipState
|
||||
{
|
||||
VipStateOffline = 0,
|
||||
VipStateOnline = 1,
|
||||
VipStatePending = 2
|
||||
};
|
||||
|
||||
enum SpeedFormula
|
||||
{
|
||||
SpeedFormulaA = 0,
|
||||
SpeedFormulaB,
|
||||
SpeedFormulaC,
|
||||
LastSpeedFormula
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
102
src/client/container.cpp
Normal file
102
src/client/container.cpp
Normal file
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
* Copyright (c) 2010-2013 OTClient <https://github.com/edubart/otclient>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "container.h"
|
||||
#include "item.h"
|
||||
|
||||
Container::Container(int id, int capacity, const std::string& name, const ItemPtr& containerItem, bool hasParent)
|
||||
{
|
||||
m_id = id;
|
||||
m_capacity = capacity;
|
||||
m_name = name;
|
||||
m_containerItem = containerItem;
|
||||
m_hasParent = hasParent;
|
||||
m_closed = false;
|
||||
}
|
||||
|
||||
ItemPtr Container::getItem(int slot)
|
||||
{
|
||||
if(slot < 0 || slot >= (int)m_items.size())
|
||||
return nullptr;
|
||||
return m_items[slot];
|
||||
}
|
||||
|
||||
void Container::onOpen(const ContainerPtr& previousContainer)
|
||||
{
|
||||
callLuaField("onOpen", previousContainer);
|
||||
}
|
||||
|
||||
void Container::onClose()
|
||||
{
|
||||
m_closed = true;
|
||||
callLuaField("onClose");
|
||||
}
|
||||
|
||||
void Container::onAddItem(const ItemPtr& item)
|
||||
{
|
||||
m_items.push_front(item);
|
||||
updateItemsPositions();
|
||||
|
||||
callLuaField("onAddItem", 0, item);
|
||||
}
|
||||
|
||||
void Container::onAddItems(const std::vector<ItemPtr>& items)
|
||||
{
|
||||
for(const ItemPtr& item : items)
|
||||
m_items.push_back(item);
|
||||
updateItemsPositions();
|
||||
}
|
||||
|
||||
void Container::onUpdateItem(int slot, const ItemPtr& item)
|
||||
{
|
||||
if(slot < 0 || slot >= (int)m_items.size()) {
|
||||
g_logger.traceError("slot not found");
|
||||
return;
|
||||
}
|
||||
|
||||
ItemPtr oldItem = m_items[slot];
|
||||
m_items[slot] = item;
|
||||
item->setPosition(getSlotPosition(slot));
|
||||
|
||||
callLuaField("onUpdateItem", slot, item, oldItem);
|
||||
}
|
||||
|
||||
void Container::onRemoveItem(int slot)
|
||||
{
|
||||
if(slot < 0 || slot >= (int)m_items.size()) {
|
||||
g_logger.traceError("slot not found");
|
||||
return;
|
||||
}
|
||||
|
||||
ItemPtr item = m_items[slot];
|
||||
m_items.erase(m_items.begin() + slot);
|
||||
|
||||
updateItemsPositions();
|
||||
|
||||
callLuaField("onRemoveItem", slot, item);
|
||||
}
|
||||
|
||||
void Container::updateItemsPositions()
|
||||
{
|
||||
for(int slot = 0; slot < (int)m_items.size(); ++slot)
|
||||
m_items[slot]->setPosition(getSlotPosition(slot));
|
||||
}
|
||||
71
src/client/container.h
Normal file
71
src/client/container.h
Normal file
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Copyright (c) 2010-2013 OTClient <https://github.com/edubart/otclient>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef CONTAINER_H
|
||||
#define CONTAINER_H
|
||||
|
||||
#include "declarations.h"
|
||||
#include "item.h"
|
||||
|
||||
#include <framework/luaengine/luaobject.h>
|
||||
|
||||
// @bindclass
|
||||
class Container : public LuaObject
|
||||
{
|
||||
protected:
|
||||
Container(int id, int capacity, const std::string& name, const ItemPtr& containerItem, bool hasParent);
|
||||
|
||||
public:
|
||||
ItemPtr getItem(int slot);
|
||||
std::deque<ItemPtr> getItems() { return m_items; }
|
||||
int getItemsCount() { return m_items.size(); }
|
||||
Position getSlotPosition(int slot) { return Position(0xffff, m_id | 0x40, slot); }
|
||||
int getId() { return m_id; }
|
||||
int getCapacity() { return m_capacity; }
|
||||
ItemPtr getContainerItem() { return m_containerItem; }
|
||||
std::string getName() { return m_name; }
|
||||
bool hasParent() { return m_hasParent; }
|
||||
bool isClosed() { return m_closed; }
|
||||
|
||||
protected:
|
||||
void onOpen(const ContainerPtr& previousContainer);
|
||||
void onClose();
|
||||
void onAddItem(const ItemPtr& item);
|
||||
void onAddItems(const std::vector<ItemPtr>& items);
|
||||
void onUpdateItem(int slot, const ItemPtr& item);
|
||||
void onRemoveItem(int slot);
|
||||
|
||||
friend class Game;
|
||||
|
||||
private:
|
||||
void updateItemsPositions();
|
||||
|
||||
int m_id;
|
||||
int m_capacity;
|
||||
ItemPtr m_containerItem;
|
||||
std::string m_name;
|
||||
bool m_hasParent;
|
||||
bool m_closed;
|
||||
std::deque<ItemPtr> m_items;
|
||||
};
|
||||
|
||||
#endif
|
||||
776
src/client/creature.cpp
Normal file
776
src/client/creature.cpp
Normal file
@@ -0,0 +1,776 @@
|
||||
/*
|
||||
* Copyright (c) 2010-2013 OTClient <https://github.com/edubart/otclient>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "creature.h"
|
||||
#include "thingtypemanager.h"
|
||||
#include "localplayer.h"
|
||||
#include "map.h"
|
||||
#include "tile.h"
|
||||
#include "item.h"
|
||||
#include "game.h"
|
||||
#include "effect.h"
|
||||
#include "luavaluecasts.h"
|
||||
#include "lightview.h"
|
||||
|
||||
#include <framework/graphics/graphics.h>
|
||||
#include <framework/core/eventdispatcher.h>
|
||||
#include <framework/core/clock.h>
|
||||
|
||||
#include <framework/graphics/paintershaderprogram.h>
|
||||
#include <framework/graphics/painterogl2_shadersources.h>
|
||||
#include <framework/graphics/texturemanager.h>
|
||||
#include <framework/graphics/framebuffermanager.h>
|
||||
#include "spritemanager.h"
|
||||
|
||||
Creature::Creature() : Thing()
|
||||
{
|
||||
m_id = 0;
|
||||
m_healthPercent = 100;
|
||||
m_speed = 200;
|
||||
m_direction = Otc::South;
|
||||
m_walkAnimationPhase = 0;
|
||||
m_walkedPixels = 0;
|
||||
m_walkTurnDirection = Otc::InvalidDirection;
|
||||
m_skull = Otc::SkullNone;
|
||||
m_shield = Otc::ShieldNone;
|
||||
m_emblem = Otc::EmblemNone;
|
||||
m_lastStepDirection = Otc::InvalidDirection;
|
||||
m_nameCache.setFont(g_fonts.getFont("verdana-11px-rounded"));
|
||||
m_nameCache.setAlign(Fw::AlignTopCenter);
|
||||
m_footStep = 0;
|
||||
m_speedFormula.fill(-1);
|
||||
}
|
||||
|
||||
void Creature::draw(const Point& dest, float scaleFactor, bool animate, LightView *lightView)
|
||||
{
|
||||
if(!canBeSeen())
|
||||
return;
|
||||
|
||||
Point animationOffset = animate ? m_walkOffset : Point(0,0);
|
||||
|
||||
if(m_showTimedSquare && animate) {
|
||||
g_painter->setColor(m_timedSquareColor);
|
||||
g_painter->drawBoundingRect(Rect(dest + (animationOffset - getDisplacement() + 2)*scaleFactor, Size(28, 28)*scaleFactor), std::max((int)(2*scaleFactor), 1));
|
||||
g_painter->setColor(Color::white);
|
||||
}
|
||||
|
||||
if(m_showStaticSquare && animate) {
|
||||
g_painter->setColor(m_staticSquareColor);
|
||||
g_painter->drawBoundingRect(Rect(dest + (animationOffset - getDisplacement())*scaleFactor, Size(Otc::TILE_PIXELS, Otc::TILE_PIXELS)*scaleFactor), std::max((int)(2*scaleFactor), 1));
|
||||
g_painter->setColor(Color::white);
|
||||
}
|
||||
|
||||
internalDrawOutfit(dest + animationOffset * scaleFactor, scaleFactor, animate, animate, m_direction);
|
||||
m_footStepDrawn = true;
|
||||
|
||||
if(lightView) {
|
||||
Light light = rawGetThingType()->getLight();
|
||||
if(m_light.intensity != light.intensity || m_light.color != light.color)
|
||||
light = m_light;
|
||||
|
||||
// local player always have a minimum light in complete darkness
|
||||
if(isLocalPlayer() && (g_map.getLight().intensity < 64 || m_position.z > Otc::SEA_FLOOR)) {
|
||||
light.intensity = std::max<uint8>(light.intensity, 2);
|
||||
if(light.color == 0 || light.color > 215)
|
||||
light.color = 215;
|
||||
}
|
||||
|
||||
if(light.intensity > 0)
|
||||
lightView->addLightSource(dest + (animationOffset + Point(16,16)) * scaleFactor, scaleFactor, light);
|
||||
}
|
||||
}
|
||||
|
||||
void Creature::internalDrawOutfit(Point dest, float scaleFactor, bool animateWalk, bool animateIdle, Otc::Direction direction, LightView *lightView)
|
||||
{
|
||||
// outfit is a real creature
|
||||
if(m_outfit.getCategory() == ThingCategoryCreature) {
|
||||
int animationPhase = animateWalk ? m_walkAnimationPhase : 0;
|
||||
|
||||
if(isAnimateAlways() && animateIdle) {
|
||||
int ticksPerFrame = 1000 / getAnimationPhases();
|
||||
animationPhase = (g_clock.millis() % (ticksPerFrame * getAnimationPhases())) / ticksPerFrame;
|
||||
}
|
||||
|
||||
// xPattern => creature direction
|
||||
int xPattern;
|
||||
if(direction == Otc::NorthEast || direction == Otc::SouthEast)
|
||||
xPattern = Otc::East;
|
||||
else if(direction == Otc::NorthWest || direction == Otc::SouthWest)
|
||||
xPattern = Otc::West;
|
||||
else
|
||||
xPattern = direction;
|
||||
|
||||
int zPattern = 0;
|
||||
if(m_outfit.getMount() != 0) {
|
||||
auto datType = g_things.rawGetThingType(m_outfit.getMount(), ThingCategoryCreature);
|
||||
dest -= datType->getDisplacement() * scaleFactor;
|
||||
datType->draw(dest, scaleFactor, 0, xPattern, 0, 0, animationPhase, lightView);
|
||||
dest += getDisplacement() * scaleFactor;
|
||||
zPattern = 1;
|
||||
}
|
||||
|
||||
// yPattern => creature addon
|
||||
for(int yPattern = 0; yPattern < getNumPatternY(); yPattern++) {
|
||||
|
||||
// continue if we dont have this addon
|
||||
if(yPattern > 0 && !(m_outfit.getAddons() & (1 << (yPattern-1))))
|
||||
continue;
|
||||
|
||||
auto datType = rawGetThingType();
|
||||
datType->draw(dest, scaleFactor, 0, xPattern, yPattern, zPattern, animationPhase, yPattern == 0 ? lightView : nullptr);
|
||||
|
||||
if(getLayers() > 1) {
|
||||
Color oldColor = g_painter->getColor();
|
||||
Painter::CompositionMode oldComposition = g_painter->getCompositionMode();
|
||||
g_painter->setCompositionMode(Painter::CompositionMode_Multiply);
|
||||
g_painter->setColor(m_outfit.getHeadColor());
|
||||
datType->draw(dest, scaleFactor, SpriteMaskYellow, xPattern, yPattern, zPattern, animationPhase);
|
||||
g_painter->setColor(m_outfit.getBodyColor());
|
||||
datType->draw(dest, scaleFactor, SpriteMaskRed, xPattern, yPattern, zPattern, animationPhase);
|
||||
g_painter->setColor(m_outfit.getLegsColor());
|
||||
datType->draw(dest, scaleFactor, SpriteMaskGreen, xPattern, yPattern, zPattern, animationPhase);
|
||||
g_painter->setColor(m_outfit.getFeetColor());
|
||||
datType->draw(dest, scaleFactor, SpriteMaskBlue, xPattern, yPattern, zPattern, animationPhase);
|
||||
g_painter->setColor(oldColor);
|
||||
g_painter->setCompositionMode(oldComposition);
|
||||
}
|
||||
}
|
||||
// outfit is a creature imitating an item or the invisible effect
|
||||
} else {
|
||||
ThingType *type = g_things.rawGetThingType(m_outfit.getAuxId(), m_outfit.getCategory());
|
||||
|
||||
int animationPhase = 0;
|
||||
int animationPhases = type->getAnimationPhases();
|
||||
int animateTicks = Otc::ITEM_TICKS_PER_FRAME;
|
||||
|
||||
// when creature is an effect we cant render the first and last animation phase,
|
||||
// instead we should loop in the phases between
|
||||
if(m_outfit.getCategory() == ThingCategoryEffect) {
|
||||
animationPhases = std::max(1, animationPhases-2);
|
||||
animateTicks = Otc::INVISIBLE_TICKS_PER_FRAME;
|
||||
}
|
||||
|
||||
if(animationPhases > 1) {
|
||||
if(animateIdle)
|
||||
animationPhase = (g_clock.millis() % (animateTicks * animationPhases)) / animateTicks;
|
||||
else
|
||||
animationPhase = animationPhases-1;
|
||||
}
|
||||
|
||||
if(m_outfit.getCategory() == ThingCategoryEffect)
|
||||
animationPhase = std::min(animationPhase+1, animationPhases);
|
||||
|
||||
type->draw(dest - (getDisplacement() * scaleFactor), scaleFactor, 0, 0, 0, 0, animationPhase, lightView);
|
||||
}
|
||||
}
|
||||
|
||||
void Creature::drawOutfit(const Rect& destRect, bool resize)
|
||||
{
|
||||
int exactSize;
|
||||
if(m_outfit.getCategory() == ThingCategoryCreature)
|
||||
exactSize = getExactSize();
|
||||
else
|
||||
exactSize = g_things.rawGetThingType(m_outfit.getAuxId(), m_outfit.getCategory())->getExactSize();
|
||||
|
||||
if(g_graphics.canUseFBO()) {
|
||||
const FrameBufferPtr& outfitBuffer = g_framebuffers.getTemporaryFrameBuffer();
|
||||
outfitBuffer->resize(Size(2*Otc::TILE_PIXELS, 2*Otc::TILE_PIXELS));
|
||||
outfitBuffer->bind();
|
||||
g_painter->setAlphaWriting(true);
|
||||
g_painter->clear(Color::alpha);
|
||||
internalDrawOutfit(Point(Otc::TILE_PIXELS,Otc::TILE_PIXELS) + getDisplacement(), 1, false, true, Otc::South);
|
||||
outfitBuffer->release();
|
||||
|
||||
Rect srcRect;
|
||||
if(resize)
|
||||
srcRect.resize(exactSize, exactSize);
|
||||
else
|
||||
srcRect.resize(2*Otc::TILE_PIXELS*0.75f, 2*Otc::TILE_PIXELS*0.75f);
|
||||
srcRect.moveBottomRight(Point(2*Otc::TILE_PIXELS - 1, 2*Otc::TILE_PIXELS - 1));
|
||||
outfitBuffer->draw(destRect, srcRect);
|
||||
} else {
|
||||
float scaleFactor;
|
||||
if(resize)
|
||||
scaleFactor = destRect.width() / (float)exactSize;
|
||||
else
|
||||
scaleFactor = destRect.width() / (float)(2*Otc::TILE_PIXELS*0.75f);
|
||||
Point dest = destRect.bottomRight() - (Point(Otc::TILE_PIXELS,Otc::TILE_PIXELS) - getDisplacement())*scaleFactor;
|
||||
internalDrawOutfit(dest, scaleFactor, false, true, Otc::South);
|
||||
}
|
||||
}
|
||||
|
||||
void Creature::drawInformation(const Point& point, bool useGray, const Rect& parentRect)
|
||||
{
|
||||
if(m_healthPercent < 1) // creature is dead
|
||||
return;
|
||||
|
||||
Color fillColor = Color(96, 96, 96);
|
||||
|
||||
if(!useGray)
|
||||
fillColor = m_informationColor;
|
||||
|
||||
// calculate main rects
|
||||
Rect backgroundRect = Rect(point.x-(13.5), point.y, 27, 4);
|
||||
backgroundRect.bind(parentRect);
|
||||
|
||||
Size nameSize = m_nameCache.getTextSize();
|
||||
Rect textRect = Rect(point.x - nameSize.width() / 2.0, point.y-12, nameSize);
|
||||
textRect.bind(parentRect);
|
||||
|
||||
// distance them
|
||||
if(textRect.top() == parentRect.top())
|
||||
backgroundRect.moveTop(textRect.top() + 12);
|
||||
if(backgroundRect.bottom() == parentRect.bottom())
|
||||
textRect.moveTop(backgroundRect.top() - 12);
|
||||
|
||||
// health rect is based on background rect, so no worries
|
||||
Rect healthRect = backgroundRect.expanded(-1);
|
||||
healthRect.setWidth((m_healthPercent / 100.0) * 25);
|
||||
|
||||
// draw
|
||||
g_painter->setColor(Color::black);
|
||||
g_painter->drawFilledRect(backgroundRect);
|
||||
|
||||
g_painter->setColor(fillColor);
|
||||
g_painter->drawFilledRect(healthRect);
|
||||
|
||||
m_nameCache.draw(textRect);
|
||||
|
||||
if(m_skull != Otc::SkullNone && m_skullTexture) {
|
||||
g_painter->setColor(Color::white);
|
||||
Rect skullRect = Rect(backgroundRect.x() + 13.5 + 12, backgroundRect.y() + 5, m_skullTexture->getSize());
|
||||
g_painter->drawTexturedRect(skullRect, m_skullTexture);
|
||||
}
|
||||
if(m_shield != Otc::ShieldNone && m_shieldTexture && m_showShieldTexture) {
|
||||
g_painter->setColor(Color::white);
|
||||
Rect shieldRect = Rect(backgroundRect.x() + 13.5, backgroundRect.y() + 5, m_shieldTexture->getSize());
|
||||
g_painter->drawTexturedRect(shieldRect, m_shieldTexture);
|
||||
}
|
||||
if(m_emblem != Otc::EmblemNone && m_emblemTexture) {
|
||||
g_painter->setColor(Color::white);
|
||||
Rect emblemRect = Rect(backgroundRect.x() + 13.5 + 12, backgroundRect.y() + 16, m_emblemTexture->getSize());
|
||||
g_painter->drawTexturedRect(emblemRect, m_emblemTexture);
|
||||
}
|
||||
}
|
||||
|
||||
void Creature::turn(Otc::Direction direction)
|
||||
{
|
||||
// if is not walking change the direction right away
|
||||
if(!m_walking)
|
||||
setDirection(direction);
|
||||
// schedules to set the new direction when walk ends
|
||||
else
|
||||
m_walkTurnDirection = direction;
|
||||
}
|
||||
|
||||
void Creature::walk(const Position& oldPos, const Position& newPos)
|
||||
{
|
||||
if(oldPos == newPos)
|
||||
return;
|
||||
|
||||
// get walk direction
|
||||
m_lastStepDirection = oldPos.getDirectionFromPosition(newPos);
|
||||
m_lastStepFromPosition = oldPos;
|
||||
m_lastStepToPosition = newPos;
|
||||
|
||||
// set current walking direction
|
||||
setDirection(m_lastStepDirection);
|
||||
|
||||
// starts counting walk
|
||||
m_walking = true;
|
||||
m_walkTimer.restart();
|
||||
m_walkedPixels = 0;
|
||||
|
||||
// no direction need to be changed when the walk ends
|
||||
m_walkTurnDirection = Otc::InvalidDirection;
|
||||
|
||||
// starts updating walk
|
||||
nextWalkUpdate();
|
||||
}
|
||||
|
||||
void Creature::stopWalk()
|
||||
{
|
||||
if(!m_walking)
|
||||
return;
|
||||
|
||||
// reset walk animation states
|
||||
m_walkOffset = Point(0,0);
|
||||
m_walkAnimationPhase = 0;
|
||||
|
||||
// stops the walk right away
|
||||
terminateWalk();
|
||||
}
|
||||
|
||||
void Creature::onPositionChange(const Position& newPos, const Position& oldPos)
|
||||
{
|
||||
callLuaField("onPositionChange", newPos, oldPos);
|
||||
}
|
||||
|
||||
void Creature::onAppear()
|
||||
{
|
||||
// cancel any disappear event
|
||||
if(m_disappearEvent) {
|
||||
m_disappearEvent->cancel();
|
||||
m_disappearEvent = nullptr;
|
||||
}
|
||||
|
||||
// creature appeared the first time or wasn't seen for a long time
|
||||
if(m_removed) {
|
||||
stopWalk();
|
||||
m_removed = false;
|
||||
callLuaField("onAppear");
|
||||
// walk
|
||||
} else if(m_oldPosition != m_position && m_oldPosition.isInRange(m_position,1,1) && m_allowAppearWalk) {
|
||||
m_allowAppearWalk = false;
|
||||
walk(m_oldPosition, m_position);
|
||||
callLuaField("onWalk", m_oldPosition, m_position);
|
||||
// teleport
|
||||
} else if(m_oldPosition != m_position) {
|
||||
stopWalk();
|
||||
callLuaField("onDisappear");
|
||||
callLuaField("onAppear");
|
||||
} // else turn
|
||||
}
|
||||
|
||||
void Creature::onDisappear()
|
||||
{
|
||||
if(m_disappearEvent)
|
||||
m_disappearEvent->cancel();
|
||||
|
||||
m_oldPosition = m_position;
|
||||
|
||||
// a pair onDisappear and onAppear events are fired even when creatures walks or turns,
|
||||
// so we must filter
|
||||
auto self = static_self_cast<Creature>();
|
||||
m_disappearEvent = g_dispatcher.addEvent([self] {
|
||||
self->m_removed = true;
|
||||
self->stopWalk();
|
||||
|
||||
self->callLuaField("onDisappear");
|
||||
|
||||
// invalidate this creature position
|
||||
if(!self->isLocalPlayer())
|
||||
self->setPosition(Position());
|
||||
self->m_oldPosition = Position();
|
||||
self->m_disappearEvent = nullptr;
|
||||
});
|
||||
}
|
||||
|
||||
void Creature::updateWalkAnimation(int totalPixelsWalked)
|
||||
{
|
||||
// update outfit animation
|
||||
if(m_outfit.getCategory() != ThingCategoryCreature)
|
||||
return;
|
||||
|
||||
int footAnimPhases = getAnimationPhases() - 1;
|
||||
if(totalPixelsWalked == 32 || footAnimPhases == 0)
|
||||
m_walkAnimationPhase = 0;
|
||||
else if(m_footStepDrawn && m_footTimer.ticksElapsed() >= getStepDuration(true) / 4 ) {
|
||||
m_footStep++;
|
||||
m_walkAnimationPhase = 1 + (m_footStep % footAnimPhases);
|
||||
m_footStepDrawn = false;
|
||||
m_footTimer.restart();
|
||||
}
|
||||
}
|
||||
|
||||
void Creature::updateWalkOffset(int totalPixelsWalked)
|
||||
{
|
||||
m_walkOffset = Point(0,0);
|
||||
if(m_direction == Otc::North || m_direction == Otc::NorthEast || m_direction == Otc::NorthWest)
|
||||
m_walkOffset.y = 32 - totalPixelsWalked;
|
||||
else if(m_direction == Otc::South || m_direction == Otc::SouthEast || m_direction == Otc::SouthWest)
|
||||
m_walkOffset.y = totalPixelsWalked - 32;
|
||||
|
||||
if(m_direction == Otc::East || m_direction == Otc::NorthEast || m_direction == Otc::SouthEast)
|
||||
m_walkOffset.x = totalPixelsWalked - 32;
|
||||
else if(m_direction == Otc::West || m_direction == Otc::NorthWest || m_direction == Otc::SouthWest)
|
||||
m_walkOffset.x = 32 - totalPixelsWalked;
|
||||
}
|
||||
|
||||
void Creature::updateWalkingTile()
|
||||
{
|
||||
// determine new walking tile
|
||||
TilePtr newWalkingTile;
|
||||
Rect virtualCreatureRect(Otc::TILE_PIXELS + (m_walkOffset.x - getDisplacementX()),
|
||||
Otc::TILE_PIXELS + (m_walkOffset.y - getDisplacementY()),
|
||||
Otc::TILE_PIXELS, Otc::TILE_PIXELS);
|
||||
for(int xi = -1; xi <= 1 && !newWalkingTile; ++xi) {
|
||||
for(int yi = -1; yi <= 1 && !newWalkingTile; ++yi) {
|
||||
Rect virtualTileRect((xi+1)*Otc::TILE_PIXELS, (yi+1)*Otc::TILE_PIXELS, Otc::TILE_PIXELS, Otc::TILE_PIXELS);
|
||||
|
||||
// only render creatures where bottom right is inside tile rect
|
||||
if(virtualTileRect.contains(virtualCreatureRect.bottomRight())) {
|
||||
newWalkingTile = g_map.getOrCreateTile(m_position.translated(xi, yi, 0));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(newWalkingTile != m_walkingTile) {
|
||||
if(m_walkingTile)
|
||||
m_walkingTile->removeWalkingCreature(static_self_cast<Creature>());
|
||||
if(newWalkingTile) {
|
||||
newWalkingTile->addWalkingCreature(static_self_cast<Creature>());
|
||||
|
||||
// recache visible tiles in map views
|
||||
if(newWalkingTile->isEmpty())
|
||||
g_map.notificateTileUpdateToMapViews(newWalkingTile->getPosition());
|
||||
}
|
||||
m_walkingTile = newWalkingTile;
|
||||
}
|
||||
}
|
||||
|
||||
void Creature::nextWalkUpdate()
|
||||
{
|
||||
// remove any previous scheduled walk updates
|
||||
if(m_walkUpdateEvent)
|
||||
m_walkUpdateEvent->cancel();
|
||||
|
||||
// do the update
|
||||
updateWalk();
|
||||
|
||||
// schedules next update
|
||||
if(m_walking) {
|
||||
auto self = static_self_cast<Creature>();
|
||||
m_walkUpdateEvent = g_dispatcher.scheduleEvent([self] {
|
||||
self->m_walkUpdateEvent = nullptr;
|
||||
self->nextWalkUpdate();
|
||||
}, getStepDuration() / 32);
|
||||
}
|
||||
}
|
||||
|
||||
void Creature::updateWalk()
|
||||
{
|
||||
float walkTicksPerPixel = getStepDuration(true) / 32;
|
||||
int totalPixelsWalked = std::min(m_walkTimer.ticksElapsed() / walkTicksPerPixel, 32.0f);
|
||||
|
||||
// needed for paralyze effect
|
||||
m_walkedPixels = std::max(m_walkedPixels, totalPixelsWalked);
|
||||
|
||||
// update walk animation and offsets
|
||||
updateWalkAnimation(totalPixelsWalked);
|
||||
updateWalkOffset(m_walkedPixels);
|
||||
updateWalkingTile();
|
||||
|
||||
// terminate walk
|
||||
if(m_walking && m_walkTimer.ticksElapsed() >= getStepDuration())
|
||||
terminateWalk();
|
||||
}
|
||||
|
||||
void Creature::terminateWalk()
|
||||
{
|
||||
// remove any scheduled walk update
|
||||
if(m_walkUpdateEvent) {
|
||||
m_walkUpdateEvent->cancel();
|
||||
m_walkUpdateEvent = nullptr;
|
||||
}
|
||||
|
||||
// now the walk has ended, do any scheduled turn
|
||||
if(m_walkTurnDirection != Otc::InvalidDirection) {
|
||||
setDirection(m_walkTurnDirection);
|
||||
m_walkTurnDirection = Otc::InvalidDirection;
|
||||
}
|
||||
|
||||
if(m_walkingTile) {
|
||||
m_walkingTile->removeWalkingCreature(static_self_cast<Creature>());
|
||||
m_walkingTile = nullptr;
|
||||
}
|
||||
|
||||
m_walking = false;
|
||||
m_walkedPixels = 0;
|
||||
}
|
||||
|
||||
void Creature::setName(const std::string& name)
|
||||
{
|
||||
m_nameCache.setText(name);
|
||||
m_name = name;
|
||||
}
|
||||
|
||||
void Creature::setHealthPercent(uint8 healthPercent)
|
||||
{
|
||||
m_informationColor = Color::black;
|
||||
|
||||
if(healthPercent > 92) {
|
||||
m_informationColor.setGreen(188);
|
||||
}
|
||||
else if(healthPercent > 60) {
|
||||
m_informationColor.setRed(80);
|
||||
m_informationColor.setGreen(161);
|
||||
m_informationColor.setBlue(80);
|
||||
}
|
||||
else if(healthPercent > 30) {
|
||||
m_informationColor.setRed(161);
|
||||
m_informationColor.setGreen(161);
|
||||
}
|
||||
else if(healthPercent > 8) {
|
||||
m_informationColor.setRed(160);
|
||||
m_informationColor.setGreen(39);
|
||||
m_informationColor.setBlue(39);
|
||||
}
|
||||
else if(healthPercent > 3) {
|
||||
m_informationColor.setRed(160);
|
||||
}
|
||||
else {
|
||||
m_informationColor.setRed(79);
|
||||
}
|
||||
|
||||
m_healthPercent = healthPercent;
|
||||
callLuaField("onHealthPercentChange", healthPercent);
|
||||
}
|
||||
|
||||
void Creature::setDirection(Otc::Direction direction)
|
||||
{
|
||||
assert(direction != Otc::InvalidDirection);
|
||||
m_direction = direction;
|
||||
}
|
||||
|
||||
void Creature::setOutfit(const Outfit& outfit)
|
||||
{
|
||||
Outfit oldOutfit = outfit;
|
||||
if(outfit.getCategory() != ThingCategoryCreature) {
|
||||
if(!g_things.isValidDatId(outfit.getAuxId(), outfit.getCategory()))
|
||||
return;
|
||||
m_outfit.setAuxId(outfit.getAuxId());
|
||||
m_outfit.setCategory(outfit.getCategory());
|
||||
} else {
|
||||
if(outfit.getId() > 0 && !g_things.isValidDatId(outfit.getId(), ThingCategoryCreature))
|
||||
return;
|
||||
m_outfit = outfit;
|
||||
}
|
||||
m_walkAnimationPhase = 0; // might happen when player is walking and outfit is changed.
|
||||
|
||||
callLuaField("onOutfitChange", m_outfit, oldOutfit);
|
||||
}
|
||||
|
||||
void Creature::setSpeed(uint16 speed)
|
||||
{
|
||||
uint16 oldSpeed = m_speed;
|
||||
m_speed = speed;
|
||||
|
||||
// speed can change while walking (utani hur, paralyze, etc..)
|
||||
if(m_walking)
|
||||
nextWalkUpdate();
|
||||
|
||||
callLuaField("onSpeedChange", m_speed, oldSpeed);
|
||||
}
|
||||
|
||||
void Creature::setSkull(uint8 skull)
|
||||
{
|
||||
m_skull = skull;
|
||||
callLuaField("onSkullChange", m_skull);
|
||||
}
|
||||
|
||||
void Creature::setShield(uint8 shield)
|
||||
{
|
||||
m_shield = shield;
|
||||
callLuaField("onShieldChange", m_shield);
|
||||
}
|
||||
|
||||
void Creature::setEmblem(uint8 emblem)
|
||||
{
|
||||
m_emblem = emblem;
|
||||
callLuaField("onEmblemChange", m_emblem);
|
||||
}
|
||||
|
||||
void Creature::setSkullTexture(const std::string& filename)
|
||||
{
|
||||
m_skullTexture = g_textures.getTexture(filename);
|
||||
}
|
||||
|
||||
void Creature::setShieldTexture(const std::string& filename, bool blink)
|
||||
{
|
||||
m_shieldTexture = g_textures.getTexture(filename);
|
||||
m_showShieldTexture = true;
|
||||
|
||||
if(blink && !m_shieldBlink) {
|
||||
auto self = static_self_cast<Creature>();
|
||||
g_dispatcher.scheduleEvent([self]() {
|
||||
self->updateShield();
|
||||
}, SHIELD_BLINK_TICKS);
|
||||
}
|
||||
|
||||
m_shieldBlink = blink;
|
||||
}
|
||||
|
||||
void Creature::setEmblemTexture(const std::string& filename)
|
||||
{
|
||||
m_emblemTexture = g_textures.getTexture(filename);
|
||||
}
|
||||
|
||||
void Creature::setSpeedFormula(double speedA, double speedB, double speedC)
|
||||
{
|
||||
m_speedFormula[Otc::SpeedFormulaA] = speedA;
|
||||
m_speedFormula[Otc::SpeedFormulaB] = speedB;
|
||||
m_speedFormula[Otc::SpeedFormulaC] = speedC;
|
||||
}
|
||||
|
||||
bool Creature::hasSpeedFormula()
|
||||
{
|
||||
return m_speedFormula[Otc::SpeedFormulaA] != -1 && m_speedFormula[Otc::SpeedFormulaB] != -1
|
||||
&& m_speedFormula[Otc::SpeedFormulaC] != -1;
|
||||
}
|
||||
|
||||
void Creature::addTimedSquare(uint8 color)
|
||||
{
|
||||
m_showTimedSquare = true;
|
||||
m_timedSquareColor = Color::from8bit(color);
|
||||
|
||||
// schedule removal
|
||||
auto self = static_self_cast<Creature>();
|
||||
g_dispatcher.scheduleEvent([self]() {
|
||||
self->removeTimedSquare();
|
||||
}, VOLATILE_SQUARE_DURATION);
|
||||
}
|
||||
|
||||
void Creature::updateShield()
|
||||
{
|
||||
m_showShieldTexture = !m_showShieldTexture;
|
||||
|
||||
if(m_shield != Otc::ShieldNone && m_shieldBlink) {
|
||||
auto self = static_self_cast<Creature>();
|
||||
g_dispatcher.scheduleEvent([self]() {
|
||||
self->updateShield();
|
||||
}, SHIELD_BLINK_TICKS);
|
||||
}
|
||||
else if(!m_shieldBlink)
|
||||
m_showShieldTexture = true;
|
||||
}
|
||||
|
||||
Point Creature::getDrawOffset()
|
||||
{
|
||||
Point drawOffset;
|
||||
if(m_walking) {
|
||||
if(m_walkingTile)
|
||||
drawOffset -= Point(1,1) * m_walkingTile->getDrawElevation();
|
||||
drawOffset += m_walkOffset;
|
||||
} else {
|
||||
const TilePtr& tile = getTile();
|
||||
if(tile)
|
||||
drawOffset -= Point(1,1) * tile->getDrawElevation();
|
||||
}
|
||||
return drawOffset;
|
||||
}
|
||||
|
||||
int Creature::getStepDuration(bool ignoreDiagonal)
|
||||
{
|
||||
int speed = m_speed;
|
||||
if(speed < 1)
|
||||
return 0;
|
||||
|
||||
if(g_game.getFeature(Otc::GameNewSpeedLaw))
|
||||
speed *= 2;
|
||||
|
||||
int groundSpeed = 0;
|
||||
Position tilePos = m_lastStepToPosition;
|
||||
if(!tilePos.isValid())
|
||||
tilePos = m_position;
|
||||
const TilePtr& tile = g_map.getTile(tilePos);
|
||||
if(tile) {
|
||||
groundSpeed = tile->getGroundSpeed();
|
||||
if(groundSpeed == 0)
|
||||
groundSpeed = 150;
|
||||
}
|
||||
|
||||
int interval = 1000;
|
||||
if(groundSpeed > 0 && speed > 0)
|
||||
interval = 1000 * groundSpeed;
|
||||
|
||||
if(g_game.getFeature(Otc::GameNewSpeedLaw) && hasSpeedFormula()) {
|
||||
int formulatedSpeed = 1;
|
||||
if(speed > -m_speedFormula[Otc::SpeedFormulaB]) {
|
||||
formulatedSpeed = std::max(1, (int)floor((m_speedFormula[Otc::SpeedFormulaA] * log((speed / 2)
|
||||
+ m_speedFormula[Otc::SpeedFormulaB]) + m_speedFormula[Otc::SpeedFormulaC]) + 0.5));
|
||||
}
|
||||
interval = std::floor(interval / (double)formulatedSpeed);
|
||||
}
|
||||
else
|
||||
interval /= speed;
|
||||
|
||||
if(g_game.getProtocolVersion() >= 900)
|
||||
interval = (interval / g_game.getServerBeat()) * g_game.getServerBeat();
|
||||
|
||||
interval = std::max(interval, g_game.getServerBeat());
|
||||
|
||||
if(!ignoreDiagonal && (m_lastStepDirection == Otc::NorthWest || m_lastStepDirection == Otc::NorthEast ||
|
||||
m_lastStepDirection == Otc::SouthWest || m_lastStepDirection == Otc::SouthEast))
|
||||
interval *= 3;
|
||||
|
||||
return interval;
|
||||
}
|
||||
|
||||
Point Creature::getDisplacement()
|
||||
{
|
||||
if(m_outfit.getCategory() == ThingCategoryEffect)
|
||||
return Point(8, 8);
|
||||
else if(m_outfit.getCategory() == ThingCategoryItem)
|
||||
return Point(0, 0);
|
||||
return Thing::getDisplacement();
|
||||
}
|
||||
|
||||
int Creature::getDisplacementX()
|
||||
{
|
||||
if(m_outfit.getCategory() == ThingCategoryEffect)
|
||||
return 8;
|
||||
else if(m_outfit.getCategory() == ThingCategoryItem)
|
||||
return 0;
|
||||
return Thing::getDisplacementX();
|
||||
}
|
||||
|
||||
int Creature::getDisplacementY()
|
||||
{
|
||||
if(m_outfit.getCategory() == ThingCategoryEffect)
|
||||
return 8;
|
||||
else if(m_outfit.getCategory() == ThingCategoryItem)
|
||||
return 0;
|
||||
return Thing::getDisplacementY();
|
||||
}
|
||||
|
||||
int Creature::getExactSize(int layer, int xPattern, int yPattern, int zPattern, int animationPhase)
|
||||
{
|
||||
int exactSize = 0;
|
||||
|
||||
animationPhase = 0;
|
||||
xPattern = Otc::South;
|
||||
|
||||
zPattern = 0;
|
||||
if(m_outfit.getMount() != 0)
|
||||
zPattern = 1;
|
||||
|
||||
for(yPattern = 0; yPattern < getNumPatternY(); yPattern++) {
|
||||
if(yPattern > 0 && !(m_outfit.getAddons() & (1 << (yPattern-1))))
|
||||
continue;
|
||||
|
||||
for(layer = 0; layer < getLayers(); ++layer)
|
||||
exactSize = std::max(exactSize, Thing::getExactSize(layer, xPattern, yPattern, zPattern, animationPhase));
|
||||
}
|
||||
|
||||
return exactSize;
|
||||
}
|
||||
|
||||
const ThingTypePtr& Creature::getThingType()
|
||||
{
|
||||
return g_things.getThingType(m_outfit.getId(), ThingCategoryCreature);
|
||||
}
|
||||
|
||||
ThingType* Creature::rawGetThingType()
|
||||
{
|
||||
return g_things.rawGetThingType(m_outfit.getId(), ThingCategoryCreature);
|
||||
}
|
||||
192
src/client/creature.h
Normal file
192
src/client/creature.h
Normal file
@@ -0,0 +1,192 @@
|
||||
/*
|
||||
* Copyright (c) 2010-2013 OTClient <https://github.com/edubart/otclient>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef CREATURE_H
|
||||
#define CREATURE_H
|
||||
|
||||
#include "thing.h"
|
||||
#include "outfit.h"
|
||||
#include "tile.h"
|
||||
#include "mapview.h"
|
||||
#include <framework/core/scheduledevent.h>
|
||||
#include <framework/core/declarations.h>
|
||||
#include <framework/core/timer.h>
|
||||
#include <framework/graphics/fontmanager.h>
|
||||
#include <framework/graphics/cachedtext.h>
|
||||
|
||||
// @bindclass
|
||||
class Creature : public Thing
|
||||
{
|
||||
public:
|
||||
enum {
|
||||
SHIELD_BLINK_TICKS = 500,
|
||||
VOLATILE_SQUARE_DURATION = 1000
|
||||
};
|
||||
|
||||
Creature();
|
||||
|
||||
virtual void draw(const Point& dest, float scaleFactor, bool animate, LightView *lightView = nullptr);
|
||||
|
||||
void internalDrawOutfit(Point dest, float scaleFactor, bool animateWalk, bool animateIdle, Otc::Direction direction, LightView *lightView = nullptr);
|
||||
void drawOutfit(const Rect& destRect, bool resize);
|
||||
void drawInformation(const Point& point, bool useGray, const Rect& parentRect);
|
||||
|
||||
void setId(uint32 id) { m_id = id; }
|
||||
void setName(const std::string& name);
|
||||
void setHealthPercent(uint8 healthPercent);
|
||||
void setDirection(Otc::Direction direction);
|
||||
void setOutfit(const Outfit& outfit);
|
||||
void setLight(const Light& light) { m_light = light; }
|
||||
void setSpeed(uint16 speed);
|
||||
void setSkull(uint8 skull);
|
||||
void setShield(uint8 shield);
|
||||
void setEmblem(uint8 emblem);
|
||||
void setSkullTexture(const std::string& filename);
|
||||
void setShieldTexture(const std::string& filename, bool blink);
|
||||
void setEmblemTexture(const std::string& filename);
|
||||
void setPassable(bool passable) { m_passable = passable; }
|
||||
void setSpeedFormula(double speedA, double speedB, double speedC);
|
||||
|
||||
void addTimedSquare(uint8 color);
|
||||
void removeTimedSquare() { m_showTimedSquare = false; }
|
||||
|
||||
void showStaticSquare(const Color& color) { m_showStaticSquare = true; m_staticSquareColor = color; }
|
||||
void hideStaticSquare() { m_showStaticSquare = false; }
|
||||
|
||||
uint32 getId() { return m_id; }
|
||||
std::string getName() { return m_name; }
|
||||
uint8 getHealthPercent() { return m_healthPercent; }
|
||||
Otc::Direction getDirection() { return m_direction; }
|
||||
Outfit getOutfit() { return m_outfit; }
|
||||
Light getLight() { return m_light; }
|
||||
uint16 getSpeed() { return m_speed; }
|
||||
uint8 getSkull() { return m_skull; }
|
||||
uint8 getShield() { return m_shield; }
|
||||
uint8 getEmblem() { return m_emblem; }
|
||||
bool isPassable() { return m_passable; }
|
||||
Point getDrawOffset();
|
||||
int getStepDuration(bool ignoreDiagonal = false);
|
||||
Point getWalkOffset() { return m_walkOffset; }
|
||||
Position getLastStepFromPosition() { return m_lastStepFromPosition; }
|
||||
Position getLastStepToPosition() { return m_lastStepToPosition; }
|
||||
float getStepProgress() { return m_walkTimer.ticksElapsed() / getStepDuration(); }
|
||||
float getStepTicksLeft() { return getStepDuration() - m_walkTimer.ticksElapsed(); }
|
||||
ticks_t getWalkTicksElapsed() { return m_walkTimer.ticksElapsed(); }
|
||||
double getSpeedFormula(Otc::SpeedFormula formula) { return m_speedFormula[formula]; }
|
||||
bool hasSpeedFormula();
|
||||
std::array<double, Otc::LastSpeedFormula> getSpeedFormulaArray() { return m_speedFormula; }
|
||||
virtual Point getDisplacement();
|
||||
virtual int getDisplacementX();
|
||||
virtual int getDisplacementY();
|
||||
virtual int getExactSize(int layer = 0, int xPattern = 0, int yPattern = 0, int zPattern = 0, int animationPhase = 0);
|
||||
|
||||
void updateShield();
|
||||
|
||||
// walk related
|
||||
void turn(Otc::Direction direction);
|
||||
virtual void walk(const Position& oldPos, const Position& newPos);
|
||||
virtual void stopWalk();
|
||||
void allowAppearWalk() { m_allowAppearWalk = true; }
|
||||
|
||||
bool isWalking() { return m_walking; }
|
||||
bool isRemoved() { return m_removed; }
|
||||
bool isInvisible() { return m_outfit.getCategory() == ThingCategoryEffect && m_outfit.getAuxId() == 13; }
|
||||
bool canBeSeen() { return !isInvisible() || isPlayer(); }
|
||||
|
||||
bool isCreature() { return true; }
|
||||
|
||||
const ThingTypePtr& getThingType();
|
||||
ThingType *rawGetThingType();
|
||||
|
||||
virtual void onPositionChange(const Position& newPos, const Position& oldPos);
|
||||
virtual void onAppear();
|
||||
virtual void onDisappear();
|
||||
|
||||
protected:
|
||||
virtual void updateWalkAnimation(int totalPixelsWalked);
|
||||
virtual void updateWalkOffset(int totalPixelsWalked);
|
||||
void updateWalkingTile();
|
||||
virtual void nextWalkUpdate();
|
||||
virtual void updateWalk();
|
||||
virtual void terminateWalk();
|
||||
|
||||
uint32 m_id;
|
||||
std::string m_name;
|
||||
uint8 m_healthPercent;
|
||||
Otc::Direction m_direction;
|
||||
Outfit m_outfit;
|
||||
Light m_light;
|
||||
int m_speed;
|
||||
uint8 m_skull;
|
||||
uint8 m_shield;
|
||||
uint8 m_emblem;
|
||||
TexturePtr m_skullTexture;
|
||||
TexturePtr m_shieldTexture;
|
||||
TexturePtr m_emblemTexture;
|
||||
stdext::boolean<true> m_showShieldTexture;
|
||||
stdext::boolean<false> m_shieldBlink;
|
||||
stdext::boolean<false> m_passable;
|
||||
Color m_timedSquareColor;
|
||||
Color m_staticSquareColor;
|
||||
stdext::boolean<false> m_showTimedSquare;
|
||||
stdext::boolean<false> m_showStaticSquare;
|
||||
stdext::boolean<true> m_removed;
|
||||
CachedText m_nameCache;
|
||||
Color m_informationColor;
|
||||
|
||||
std::array<double, Otc::LastSpeedFormula> m_speedFormula;
|
||||
|
||||
// walk related
|
||||
int m_walkAnimationPhase;
|
||||
int m_walkedPixels;
|
||||
uint m_footStep;
|
||||
Timer m_walkTimer;
|
||||
Timer m_footTimer;
|
||||
TilePtr m_walkingTile;
|
||||
stdext::boolean<false> m_walking;
|
||||
stdext::boolean<false> m_allowAppearWalk;
|
||||
stdext::boolean<false> m_footStepDrawn;
|
||||
ScheduledEventPtr m_walkUpdateEvent;
|
||||
EventPtr m_disappearEvent;
|
||||
Point m_walkOffset;
|
||||
Otc::Direction m_walkTurnDirection;
|
||||
Otc::Direction m_lastStepDirection;
|
||||
Position m_lastStepFromPosition;
|
||||
Position m_lastStepToPosition;
|
||||
Position m_oldPosition;
|
||||
};
|
||||
|
||||
// @bindclass
|
||||
class Npc : public Creature
|
||||
{
|
||||
public:
|
||||
bool isNpc() { return true; }
|
||||
};
|
||||
|
||||
// @bindclass
|
||||
class Monster : public Creature
|
||||
{
|
||||
public:
|
||||
bool isMonster() { return true; }
|
||||
};
|
||||
|
||||
#endif
|
||||
371
src/client/creatures.cpp
Normal file
371
src/client/creatures.cpp
Normal file
@@ -0,0 +1,371 @@
|
||||
/*
|
||||
* Copyright (c) 2010-2013 OTClient <https://github.com/edubart/otclient>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "creatures.h"
|
||||
#include "creature.h"
|
||||
#include "map.h"
|
||||
|
||||
#include <framework/xml/tinyxml.h>
|
||||
#include <framework/core/resourcemanager.h>
|
||||
#include <boost/filesystem.hpp>
|
||||
|
||||
CreatureManager g_creatures;
|
||||
|
||||
static bool isInZone(const Position& pos/* placePos*/,
|
||||
const Position& centerPos,
|
||||
int radius)
|
||||
{
|
||||
if(radius == -1)
|
||||
return true;
|
||||
return ((pos.x >= centerPos.x - radius) && (pos.x <= centerPos.x + radius) &&
|
||||
(pos.y >= centerPos.y - radius) && (pos.y <= centerPos.y + radius)
|
||||
);
|
||||
}
|
||||
|
||||
void CreatureManager::terminate()
|
||||
{
|
||||
clearSpawns();
|
||||
clear();
|
||||
m_nullCreature = nullptr;
|
||||
}
|
||||
|
||||
void Spawn::load(TiXmlElement* node)
|
||||
{
|
||||
Position centerPos = node->readPos("center");
|
||||
setCenterPos(centerPos);
|
||||
setRadius(node->readType<int32>("radius"));
|
||||
|
||||
CreatureTypePtr cType(nullptr);
|
||||
for(TiXmlElement* cNode = node->FirstChildElement(); cNode; cNode = cNode->NextSiblingElement()) {
|
||||
if(cNode->ValueStr() != "monster" && cNode->ValueStr() != "npc")
|
||||
stdext::throw_exception(stdext::format("invalid spawn-subnode %s", cNode->ValueStr()));
|
||||
|
||||
std::string cName = cNode->Attribute("name");
|
||||
stdext::tolower(cName);
|
||||
stdext::trim(cName);
|
||||
|
||||
if (!(cType = g_creatures.getCreatureByName(cName)))
|
||||
continue;
|
||||
|
||||
cType->setSpawnTime(cNode->readType<int>("spawntime"));
|
||||
Otc::Direction dir = Otc::North;
|
||||
int16 dir_ = cNode->readType<int16>("direction");
|
||||
if(dir_ >= Otc::East && dir_ <= Otc::West)
|
||||
dir = (Otc::Direction)dir_;
|
||||
cType->setDirection(dir);
|
||||
|
||||
centerPos.x += cNode->readType<int>("x");
|
||||
centerPos.y += cNode->readType<int>("y");
|
||||
centerPos.z = cNode->readType<int>("z");
|
||||
addCreature(centerPos, cType);
|
||||
}
|
||||
}
|
||||
|
||||
void Spawn::save(TiXmlElement*& node)
|
||||
{
|
||||
node = new TiXmlElement("spawn");
|
||||
|
||||
const Position& c = getCenterPos();
|
||||
node->SetAttribute("centerx", c.x);
|
||||
node->SetAttribute("centery", c.y);
|
||||
node->SetAttribute("centerz", c.z);
|
||||
|
||||
node->SetAttribute("radius", getRadius());
|
||||
|
||||
TiXmlElement* creatureNode = nullptr;
|
||||
|
||||
for(const auto& pair : m_creatures) {
|
||||
if(!(creatureNode = new TiXmlElement("monster")))
|
||||
stdext::throw_exception("oom?");
|
||||
|
||||
const CreatureTypePtr& creature = pair.second;
|
||||
|
||||
creatureNode->SetAttribute("name", creature->getName());
|
||||
creatureNode->SetAttribute("spawntime", creature->getSpawnTime());
|
||||
creatureNode->SetAttribute("direction", creature->getDirection());
|
||||
|
||||
const Position& placePos = pair.first;
|
||||
assert(placePos.isValid());
|
||||
|
||||
creatureNode->SetAttribute("x", placePos.x);
|
||||
creatureNode->SetAttribute("y", placePos.y);
|
||||
creatureNode->SetAttribute("z", placePos.z);
|
||||
|
||||
node->LinkEndChild(creatureNode);
|
||||
}
|
||||
}
|
||||
|
||||
void Spawn::addCreature(const Position& placePos, const CreatureTypePtr& cType)
|
||||
{
|
||||
const Position& centerPos = getCenterPos();
|
||||
int m_radius = getRadius();
|
||||
if(!isInZone(placePos, centerPos, m_radius))
|
||||
stdext::throw_exception(stdext::format("cannot place creature at %s %s %d (increment radius)",
|
||||
stdext::to_string(placePos), stdext::to_string(centerPos),
|
||||
m_radius
|
||||
));
|
||||
g_map.addThing(cType->cast(), placePos, 4);
|
||||
m_creatures.insert(std::make_pair(placePos, cType));
|
||||
}
|
||||
|
||||
void Spawn::removeCreature(const Position& pos)
|
||||
{
|
||||
auto iterator = m_creatures.find(pos);
|
||||
if(iterator != m_creatures.end()) {
|
||||
assert(iterator->first.isValid());
|
||||
assert(g_map.removeThingByPos(iterator->first, 4));
|
||||
m_creatures.erase(iterator);
|
||||
}
|
||||
}
|
||||
|
||||
CreaturePtr CreatureType::cast()
|
||||
{
|
||||
CreaturePtr ret(new Creature);
|
||||
|
||||
std::string cName = getName();
|
||||
stdext::ucwords(cName);
|
||||
ret->setName(cName);
|
||||
|
||||
ret->setDirection(getDirection());
|
||||
ret->setOutfit(getOutfit());
|
||||
return ret;
|
||||
}
|
||||
|
||||
CreatureManager::CreatureManager()
|
||||
{
|
||||
m_nullCreature = CreatureTypePtr(new CreatureType);
|
||||
}
|
||||
|
||||
void CreatureManager::clearSpawns()
|
||||
{
|
||||
for(auto pair : m_spawns)
|
||||
pair.second->clear();
|
||||
m_spawns.clear();
|
||||
}
|
||||
|
||||
void CreatureManager::loadMonsters(const std::string& file)
|
||||
{
|
||||
TiXmlDocument doc;
|
||||
doc.Parse(g_resources.loadFile(file).c_str());
|
||||
if(doc.Error())
|
||||
stdext::throw_exception(stdext::format("cannot open monsters file '%s': '%s'", file, doc.ErrorDesc()));
|
||||
|
||||
TiXmlElement* root = doc.FirstChildElement();
|
||||
if(!root || root->ValueStr() != "monsters")
|
||||
stdext::throw_exception("malformed monsters xml file");
|
||||
|
||||
for(TiXmlElement* monster = root->FirstChildElement(); monster; monster = monster->NextSiblingElement()) {
|
||||
std::string fname = file.substr(0, file.find_last_of('/')) + '/' + monster->Attribute("file");
|
||||
if(fname.substr(fname.length() - 4) != ".xml")
|
||||
fname += ".xml";
|
||||
|
||||
loadSingleCreature(fname);
|
||||
}
|
||||
|
||||
doc.Clear();
|
||||
m_loaded = true;
|
||||
}
|
||||
|
||||
void CreatureManager::loadSingleCreature(const std::string& file)
|
||||
{
|
||||
loadCreatureBuffer(g_resources.loadFile(file));
|
||||
}
|
||||
|
||||
void CreatureManager::loadNpcs(const std::string& folder)
|
||||
{
|
||||
std::string tmp = folder;
|
||||
if(!stdext::ends_with(tmp, "/"))
|
||||
tmp += "/";
|
||||
|
||||
boost::filesystem::path npcPath(boost::filesystem::current_path().generic_string() + tmp);
|
||||
if(!boost::filesystem::exists(npcPath))
|
||||
stdext::throw_exception(stdext::format("NPCs folder '%s' was not found.", folder));
|
||||
|
||||
for(boost::filesystem::directory_iterator it(npcPath), end; it != end; ++it) {
|
||||
std::string f = it->path().filename().string();
|
||||
if(boost::filesystem::is_directory(it->status()))
|
||||
continue;
|
||||
|
||||
loadCreatureBuffer(g_resources.loadFile(tmp + f));
|
||||
}
|
||||
}
|
||||
|
||||
void CreatureManager::loadSpawns(const std::string& fileName)
|
||||
{
|
||||
if(!isLoaded()) {
|
||||
g_logger.warning("creatures aren't loaded yet to load spawns.");
|
||||
return;
|
||||
}
|
||||
|
||||
if(m_spawnLoaded) {
|
||||
g_logger.warning("attempt to reload spawns.");
|
||||
return;
|
||||
}
|
||||
|
||||
TiXmlDocument doc;
|
||||
doc.Parse(g_resources.loadFile(fileName).c_str());
|
||||
if(doc.Error())
|
||||
stdext::throw_exception(stdext::format("cannot load spawns xml file '%s: '%s'", fileName, doc.ErrorDesc()));
|
||||
|
||||
TiXmlElement* root = doc.FirstChildElement();
|
||||
if(!root || root->ValueStr() != "spawns")
|
||||
stdext::throw_exception("malformed spawns file");
|
||||
|
||||
for(TiXmlElement* node = root->FirstChildElement(); node; node = node->NextSiblingElement()) {
|
||||
if(node->ValueTStr() != "spawn")
|
||||
stdext::throw_exception("invalid spawn node");
|
||||
|
||||
SpawnPtr spawn(new Spawn);
|
||||
spawn->load(node);
|
||||
m_spawns.insert(std::make_pair(spawn->getCenterPos(), spawn));
|
||||
}
|
||||
doc.Clear();
|
||||
m_spawnLoaded = true;
|
||||
}
|
||||
|
||||
void CreatureManager::saveSpawns(const std::string& fileName)
|
||||
{
|
||||
TiXmlDocument doc;
|
||||
doc.SetTabSize(2);
|
||||
|
||||
TiXmlDeclaration* decl = new TiXmlDeclaration("1.0", "UTF-8", "");
|
||||
doc.LinkEndChild(decl);
|
||||
|
||||
TiXmlElement* root = new TiXmlElement("spawns");
|
||||
doc.LinkEndChild(root);
|
||||
|
||||
for(auto pair : m_spawns) {
|
||||
TiXmlElement* elem;
|
||||
pair.second->save(elem);
|
||||
root->LinkEndChild(elem);
|
||||
}
|
||||
|
||||
if(!doc.SaveFile(fileName))
|
||||
stdext::throw_exception(stdext::format("failed to save spawns XML %s: %s", fileName, doc.ErrorDesc()));
|
||||
}
|
||||
|
||||
void CreatureManager::loadCreatureBuffer(const std::string& buffer)
|
||||
{
|
||||
TiXmlDocument doc;
|
||||
doc.Parse(buffer.c_str());
|
||||
if(doc.Error())
|
||||
stdext::throw_exception(stdext::format("cannot load creature buffer: %s", doc.ErrorDesc()));
|
||||
|
||||
TiXmlElement* root = doc.FirstChildElement();
|
||||
if(!root || (root->ValueStr() != "monster" && root->ValueStr() != "npc"))
|
||||
stdext::throw_exception("invalid root tag name");
|
||||
|
||||
std::string cName = root->Attribute("name");
|
||||
stdext::tolower(cName);
|
||||
stdext::trim(cName);
|
||||
|
||||
CreatureTypePtr newType(new CreatureType(cName));
|
||||
for(TiXmlElement* attrib = root->FirstChildElement(); attrib; attrib = attrib->NextSiblingElement()) {
|
||||
if(attrib->ValueStr() != "look")
|
||||
continue;
|
||||
|
||||
internalLoadCreatureBuffer(attrib, newType);
|
||||
break;
|
||||
}
|
||||
|
||||
doc.Clear();
|
||||
}
|
||||
|
||||
void CreatureManager::internalLoadCreatureBuffer(TiXmlElement* attrib, const CreatureTypePtr& m)
|
||||
{
|
||||
if(std::find(m_creatures.begin(), m_creatures.end(), m) != m_creatures.end())
|
||||
return;
|
||||
|
||||
Outfit out;
|
||||
|
||||
int32 type = attrib->readType<int32>("type");
|
||||
if(type > 0) {
|
||||
out.setCategory(ThingCategoryCreature);
|
||||
out.setId(type);
|
||||
} else {
|
||||
out.setCategory(ThingCategoryItem);
|
||||
out.setAuxId(attrib->readType<int32>("typeex"));
|
||||
}
|
||||
|
||||
{
|
||||
out.setHead(attrib->readType<int>(("head")));
|
||||
out.setBody(attrib->readType<int>(("body")));
|
||||
out.setLegs(attrib->readType<int>(("legs")));
|
||||
out.setFeet(attrib->readType<int>(("feet")));
|
||||
out.setAddons(attrib->readType<int>(("addons")));
|
||||
out.setMount(attrib->readType<int>(("mount")));
|
||||
}
|
||||
|
||||
m->setOutfit(out);
|
||||
m_creatures.push_back(m);
|
||||
}
|
||||
|
||||
const CreatureTypePtr& CreatureManager::getCreatureByName(std::string name)
|
||||
{
|
||||
stdext::tolower(name);
|
||||
stdext::trim(name);
|
||||
auto it = std::find_if(m_creatures.begin(), m_creatures.end(),
|
||||
[=] (const CreatureTypePtr& m) -> bool { return m->getName() == name; });
|
||||
if(it != m_creatures.end())
|
||||
return *it;
|
||||
g_logger.warning(stdext::format("could not find creature with name: %s", name));
|
||||
return m_nullCreature;
|
||||
}
|
||||
|
||||
const CreatureTypePtr& CreatureManager::getCreatureByLook(int look)
|
||||
{
|
||||
auto findFun = [=] (const CreatureTypePtr& c) -> bool
|
||||
{
|
||||
const Outfit& o = c->getOutfit();
|
||||
return o.getId() == look || o.getAuxId() == look;
|
||||
};
|
||||
auto it = std::find_if(m_creatures.begin(), m_creatures.end(), findFun);
|
||||
if(it != m_creatures.end())
|
||||
return *it;
|
||||
g_logger.warning(stdext::format("could not find creature with looktype: %d", look));
|
||||
return m_nullCreature;
|
||||
}
|
||||
|
||||
SpawnPtr CreatureManager::getSpawn(const Position& centerPos)
|
||||
{
|
||||
auto it = m_spawns.find(centerPos);
|
||||
if(it != m_spawns.end())
|
||||
return it->second;
|
||||
g_logger.debug(stdext::format("failed to find spawn at center %s",stdext::to_string(centerPos)));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
SpawnPtr CreatureManager::addSpawn(const Position& centerPos, int radius)
|
||||
{
|
||||
auto iter = m_spawns.find(centerPos);
|
||||
if(iter != m_spawns.end())
|
||||
return iter->second;
|
||||
|
||||
SpawnPtr ret(new Spawn);
|
||||
|
||||
ret->setRadius(radius);
|
||||
ret->setCenterPos(centerPos);
|
||||
|
||||
m_spawns.insert(std::make_pair(centerPos, ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
134
src/client/creatures.h
Normal file
134
src/client/creatures.h
Normal file
@@ -0,0 +1,134 @@
|
||||
/*
|
||||
* Copyright (c) 2010-2013 OTClient <https://github.com/edubart/otclient>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef CREATURES_H
|
||||
#define CREATURES_H
|
||||
|
||||
#include "declarations.h"
|
||||
#include <framework/luaengine/luaobject.h>
|
||||
#include "outfit.h"
|
||||
|
||||
enum CreatureAttr : uint8
|
||||
{
|
||||
CreatureAttrPosition = 0,
|
||||
CreatureAttrName = 1,
|
||||
CreatureAttrOutfit = 2,
|
||||
CreatureAttrSpawnTime = 3,
|
||||
CreatureAttrDir = 4
|
||||
};
|
||||
|
||||
enum SpawnAttr : uint8
|
||||
{
|
||||
SpawnAttrRadius = 0,
|
||||
SpawnAttrCenter = 1,
|
||||
SpawnAttrPos = 2
|
||||
};
|
||||
|
||||
class Spawn : public LuaObject
|
||||
{
|
||||
public:
|
||||
Spawn() = default;
|
||||
Spawn(int32 radius) { setRadius(radius); }
|
||||
|
||||
void setRadius(int32 r) { m_attribs.set(SpawnAttrRadius, r) ;}
|
||||
int32 getRadius() { return m_attribs.get<int32>(SpawnAttrRadius); }
|
||||
|
||||
void setCenterPos(const Position& pos) { m_attribs.set(SpawnAttrCenter, pos); }
|
||||
Position getCenterPos() { return m_attribs.get<Position>(SpawnAttrPos); }
|
||||
|
||||
void addCreature(const Position& placePos, const CreatureTypePtr& cType);
|
||||
void removeCreature(const Position& pos);
|
||||
void clear() { m_creatures.clear(); }
|
||||
|
||||
protected:
|
||||
void load(TiXmlElement* node);
|
||||
void save(TiXmlElement*& node);
|
||||
|
||||
private:
|
||||
stdext::dynamic_storage<uint8> m_attribs;
|
||||
std::unordered_map<Position, CreatureTypePtr, PositionHasher> m_creatures;
|
||||
friend class CreatureManager;
|
||||
};
|
||||
|
||||
class CreatureType : public LuaObject
|
||||
{
|
||||
public:
|
||||
CreatureType() = default;
|
||||
CreatureType(const std::string& name) { setName(name); }
|
||||
|
||||
void setSpawnTime(int32 spawnTime) { m_attribs.set(CreatureAttrSpawnTime, spawnTime); }
|
||||
int32 getSpawnTime() { return m_attribs.get<int32>(CreatureAttrSpawnTime); }
|
||||
|
||||
void setName(const std::string& name) { m_attribs.set(CreatureAttrName, name); }
|
||||
std::string getName() { return m_attribs.get<std::string>(CreatureAttrName); }
|
||||
|
||||
void setOutfit(const Outfit& o) { m_attribs.set(CreatureAttrOutfit, o); }
|
||||
Outfit getOutfit() { return m_attribs.get<Outfit>(CreatureAttrOutfit); }
|
||||
|
||||
void setDirection(Otc::Direction dir) { m_attribs.set(CreatureAttrDir, dir); }
|
||||
Otc::Direction getDirection() { return m_attribs.get<Otc::Direction>(CreatureAttrDir); }
|
||||
|
||||
CreaturePtr cast();
|
||||
|
||||
private:
|
||||
stdext::dynamic_storage<uint8> m_attribs;
|
||||
};
|
||||
|
||||
class CreatureManager
|
||||
{
|
||||
public:
|
||||
CreatureManager();
|
||||
void clear() { m_creatures.clear(); }
|
||||
void clearSpawns();
|
||||
void terminate();
|
||||
|
||||
void loadMonsters(const std::string& file);
|
||||
void loadSingleCreature(const std::string& file);
|
||||
void loadNpcs(const std::string& folder);
|
||||
void loadCreatureBuffer(const std::string& buffer);
|
||||
void loadSpawns(const std::string& fileName);
|
||||
void saveSpawns(const std::string& fileName);
|
||||
|
||||
const CreatureTypePtr& getCreatureByName(std::string name);
|
||||
const CreatureTypePtr& getCreatureByLook(int look);
|
||||
|
||||
SpawnPtr getSpawn(const Position& centerPos);
|
||||
SpawnPtr addSpawn(const Position& centerPos, int radius);
|
||||
|
||||
bool isLoaded() { return m_loaded; }
|
||||
bool isSpawnLoaded() { return m_spawnLoaded; }
|
||||
|
||||
const std::vector<CreatureTypePtr>& getCreatures() { return m_creatures; }
|
||||
|
||||
protected:
|
||||
void internalLoadCreatureBuffer(TiXmlElement* elem, const CreatureTypePtr& m);
|
||||
|
||||
private:
|
||||
std::vector<CreatureTypePtr> m_creatures;
|
||||
std::unordered_map<Position, SpawnPtr, PositionHasher> m_spawns;
|
||||
stdext::boolean<false> m_loaded, m_spawnLoaded;
|
||||
CreatureTypePtr m_nullCreature;
|
||||
};
|
||||
|
||||
extern CreatureManager g_creatures;
|
||||
|
||||
#endif
|
||||
102
src/client/declarations.h
Normal file
102
src/client/declarations.h
Normal file
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
* Copyright (c) 2010-2013 OTClient <https://github.com/edubart/otclient>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef OTCLIENT_DECLARATIONS_H
|
||||
#define OTCLIENT_DECLARATIONS_H
|
||||
|
||||
#include "global.h"
|
||||
#include <framework/net/declarations.h>
|
||||
#include <framework/ui/declarations.h>
|
||||
|
||||
// core
|
||||
class Map;
|
||||
class Game;
|
||||
class MapView;
|
||||
class LightView;
|
||||
class Tile;
|
||||
class Thing;
|
||||
class Item;
|
||||
class Container;
|
||||
class Creature;
|
||||
class Monster;
|
||||
class Npc;
|
||||
class Player;
|
||||
class LocalPlayer;
|
||||
class Effect;
|
||||
class Missile;
|
||||
class AnimatedText;
|
||||
class StaticText;
|
||||
class ThingType;
|
||||
class ItemType;
|
||||
class House;
|
||||
class Town;
|
||||
class CreatureType;
|
||||
class Spawn;
|
||||
|
||||
typedef stdext::shared_object_ptr<MapView> MapViewPtr;
|
||||
typedef stdext::shared_object_ptr<LightView> LightViewPtr;
|
||||
typedef stdext::shared_object_ptr<Tile> TilePtr;
|
||||
typedef stdext::shared_object_ptr<Thing> ThingPtr;
|
||||
typedef stdext::shared_object_ptr<Item> ItemPtr;
|
||||
typedef stdext::shared_object_ptr<Container> ContainerPtr;
|
||||
typedef stdext::shared_object_ptr<Creature> CreaturePtr;
|
||||
typedef stdext::shared_object_ptr<Monster> MonsterPtr;
|
||||
typedef stdext::shared_object_ptr<Npc> NpcPtr;
|
||||
typedef stdext::shared_object_ptr<Player> PlayerPtr;
|
||||
typedef stdext::shared_object_ptr<LocalPlayer> LocalPlayerPtr;
|
||||
typedef stdext::shared_object_ptr<Effect> EffectPtr;
|
||||
typedef stdext::shared_object_ptr<Missile> MissilePtr;
|
||||
typedef stdext::shared_object_ptr<AnimatedText> AnimatedTextPtr;
|
||||
typedef stdext::shared_object_ptr<StaticText> StaticTextPtr;
|
||||
typedef stdext::shared_object_ptr<ThingType> ThingTypePtr;
|
||||
typedef stdext::shared_object_ptr<ItemType> ItemTypePtr;
|
||||
typedef stdext::shared_object_ptr<House> HousePtr;
|
||||
typedef stdext::shared_object_ptr<Town> TownPtr;
|
||||
typedef stdext::shared_object_ptr<CreatureType> CreatureTypePtr;
|
||||
typedef stdext::shared_object_ptr<Spawn> SpawnPtr;
|
||||
|
||||
typedef std::vector<ThingPtr> ThingList;
|
||||
typedef std::vector<ThingTypePtr> ThingTypeList;
|
||||
typedef std::vector<ItemTypePtr> ItemTypeList;
|
||||
typedef std::vector<HousePtr> HouseList;
|
||||
typedef std::vector<TownPtr> TownList;
|
||||
typedef std::unordered_map<Position, TilePtr, PositionHasher> TileMap;
|
||||
|
||||
// net
|
||||
class ProtocolLogin;
|
||||
class ProtocolGame;
|
||||
|
||||
typedef stdext::shared_object_ptr<ProtocolGame> ProtocolGamePtr;
|
||||
typedef stdext::shared_object_ptr<ProtocolLogin> ProtocolLoginPtr;
|
||||
|
||||
// ui
|
||||
class UIItem;
|
||||
class UICreature;
|
||||
class UIMap;
|
||||
class UIProgressRect;
|
||||
|
||||
typedef stdext::shared_object_ptr<UIItem> UIItemPtr;
|
||||
typedef stdext::shared_object_ptr<UICreature> UICreaturePtr;
|
||||
typedef stdext::shared_object_ptr<UIMap> UIMapPtr;
|
||||
typedef stdext::shared_object_ptr<UIProgressRect> UIProgressRectPtr;
|
||||
|
||||
#endif
|
||||
67
src/client/effect.cpp
Normal file
67
src/client/effect.cpp
Normal file
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Copyright (c) 2010-2013 OTClient <https://github.com/edubart/otclient>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "effect.h"
|
||||
#include "map.h"
|
||||
#include <framework/core/eventdispatcher.h>
|
||||
|
||||
void Effect::draw(const Point& dest, float scaleFactor, bool animate, LightView *lightView)
|
||||
{
|
||||
if(m_id == 0)
|
||||
return;
|
||||
|
||||
int animationPhase = 0;
|
||||
if(animate)
|
||||
animationPhase = std::min((int)(m_animationTimer.ticksElapsed() / m_phaseDuration), getAnimationPhases() - 1);
|
||||
rawGetThingType()->draw(dest, scaleFactor, 0, 0, 0, 0, animationPhase, lightView);
|
||||
}
|
||||
|
||||
void Effect::onAppear()
|
||||
{
|
||||
m_animationTimer.restart();
|
||||
m_phaseDuration = EFFECT_TICKS_PER_FRAME;
|
||||
|
||||
// hack to fix some animation phases duration, currently there is no better solution
|
||||
if(m_id == 33)
|
||||
m_phaseDuration <<= 2;
|
||||
|
||||
// schedule removal
|
||||
auto self = asEffect();
|
||||
g_dispatcher.scheduleEvent([self]() { g_map.removeThing(self); }, m_phaseDuration * getAnimationPhases());
|
||||
}
|
||||
|
||||
void Effect::setId(uint32 id)
|
||||
{
|
||||
if(!g_things.isValidDatId(id, ThingCategoryEffect))
|
||||
id = 0;
|
||||
m_id = id;
|
||||
}
|
||||
|
||||
const ThingTypePtr& Effect::getThingType()
|
||||
{
|
||||
return g_things.getThingType(m_id, ThingCategoryEffect);
|
||||
}
|
||||
|
||||
ThingType *Effect::rawGetThingType()
|
||||
{
|
||||
return g_things.rawGetThingType(m_id, ThingCategoryEffect);
|
||||
}
|
||||
58
src/client/effect.h
Normal file
58
src/client/effect.h
Normal file
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright (c) 2010-2013 OTClient <https://github.com/edubart/otclient>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef EFFECT_H
|
||||
#define EFFECT_H
|
||||
|
||||
#include <framework/global.h>
|
||||
#include <framework/core/timer.h>
|
||||
#include "thing.h"
|
||||
|
||||
// @bindclass
|
||||
class Effect : public Thing
|
||||
{
|
||||
enum {
|
||||
EFFECT_TICKS_PER_FRAME = 75
|
||||
};
|
||||
|
||||
public:
|
||||
void draw(const Point& dest, float scaleFactor, bool animate, LightView *lightView = nullptr);
|
||||
|
||||
void setId(uint32 id);
|
||||
uint32 getId() { return m_id; }
|
||||
|
||||
EffectPtr asEffect() { return static_self_cast<Effect>(); }
|
||||
bool isEffect() { return true; }
|
||||
|
||||
const ThingTypePtr& getThingType();
|
||||
ThingType *rawGetThingType();
|
||||
|
||||
protected:
|
||||
void onAppear();
|
||||
|
||||
private:
|
||||
Timer m_animationTimer;
|
||||
uint m_phaseDuration;
|
||||
uint16 m_id;
|
||||
};
|
||||
|
||||
#endif
|
||||
1365
src/client/game.cpp
Normal file
1365
src/client/game.cpp
Normal file
File diff suppressed because it is too large
Load Diff
326
src/client/game.h
Normal file
326
src/client/game.h
Normal file
@@ -0,0 +1,326 @@
|
||||
/*
|
||||
* Copyright (c) 2010-2013 OTClient <https://github.com/edubart/otclient>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef GAME_H
|
||||
#define GAME_H
|
||||
|
||||
#include "declarations.h"
|
||||
#include "item.h"
|
||||
#include "animatedtext.h"
|
||||
#include "effect.h"
|
||||
#include "creature.h"
|
||||
#include "container.h"
|
||||
#include "protocolgame.h"
|
||||
#include "localplayer.h"
|
||||
#include "outfit.h"
|
||||
#include <framework/core/timer.h>
|
||||
|
||||
#include <bitset>
|
||||
|
||||
typedef std::tuple<std::string, uint> Vip;
|
||||
|
||||
//@bindsingleton g_game
|
||||
class Game
|
||||
{
|
||||
public:
|
||||
Game();
|
||||
|
||||
void init();
|
||||
void terminate();
|
||||
|
||||
private:
|
||||
void resetGameStates();
|
||||
|
||||
protected:
|
||||
void processConnectionError(const boost::system::error_code& error);
|
||||
void processDisconnect();
|
||||
void processPing();
|
||||
void processPingBack(int elapsed);
|
||||
|
||||
void processLoginError(const std::string& error);
|
||||
void processLoginAdvice(const std::string& message);
|
||||
void processLoginWait(const std::string& message, int time);
|
||||
|
||||
void processPendingGame();
|
||||
void processEnterGame();
|
||||
|
||||
void processGameStart();
|
||||
void processGameEnd();
|
||||
void processDeath(int penality);
|
||||
|
||||
void processGMActions(const std::vector<uint8>& actions);
|
||||
void processInventoryChange(int slot, const ItemPtr& item);
|
||||
void processAttackCancel(uint seq);
|
||||
void processWalkCancel(Otc::Direction direction);
|
||||
|
||||
// message related
|
||||
void processTextMessage(Otc::MessageMode mode, const std::string& text);
|
||||
void processTalk(const std::string& name, int level, Otc::MessageMode mode, const std::string& text, int channelId, const Position& pos);
|
||||
|
||||
// container related
|
||||
void processOpenContainer(int containerId, const ItemPtr& containerItem, const std::string& name, int capacity, bool hasParent, const std::vector<ItemPtr>& items);
|
||||
void processCloseContainer(int containerId);
|
||||
void processContainerAddItem(int containerId, const ItemPtr& item);
|
||||
void processContainerUpdateItem(int containerId, int slot, const ItemPtr& item);
|
||||
void processContainerRemoveItem(int containerId, int slot);
|
||||
|
||||
// channel related
|
||||
void processChannelList(const std::vector<std::tuple<int, std::string> >& channelList);
|
||||
void processOpenChannel(int channelId, const std::string& name);
|
||||
void processOpenPrivateChannel(const std::string& name);
|
||||
void processOpenOwnPrivateChannel(int channelId, const std::string& name);
|
||||
void processCloseChannel(int channelId);
|
||||
|
||||
// rule violations
|
||||
void processRuleViolationChannel(int channelId);
|
||||
void processRuleViolationRemove(const std::string& name);
|
||||
void processRuleViolationCancel(const std::string& name);
|
||||
void processRuleViolationLock();
|
||||
|
||||
// vip related
|
||||
void processVipAdd(uint id, const std::string& name, uint status);
|
||||
void processVipStateChange(uint id, uint status);
|
||||
|
||||
// tutorial hint
|
||||
void processTutorialHint(int id);
|
||||
void processAutomapFlag(const Position& pos, int icon, const std::string& message);
|
||||
|
||||
// outfit
|
||||
void processOpenOutfitWindow(const Outfit& currentOufit, const std::vector<std::tuple<int, std::string, int> >& outfitList,
|
||||
const std::vector<std::tuple<int, std::string> >& mountList);
|
||||
|
||||
// npc trade
|
||||
void processOpenNpcTrade(const std::vector<std::tuple<ItemPtr, std::string, int, int, int> >& items);
|
||||
void processPlayerGoods(int money, const std::vector<std::tuple<ItemPtr, int> >& goods);
|
||||
void processCloseNpcTrade();
|
||||
|
||||
// player trade
|
||||
void processOwnTrade(const std::string& name, const std::vector<ItemPtr>& items);
|
||||
void processCounterTrade(const std::string& name, const std::vector<ItemPtr>& items);
|
||||
void processCloseTrade();
|
||||
|
||||
// edit text/list
|
||||
void processEditText(uint id, int itemId, int maxLength, const std::string& text, const std::string& writter, const std::string& date);
|
||||
void processEditList(uint id, int doorId, const std::string& text);
|
||||
|
||||
// questlog
|
||||
void processQuestLog(const std::vector<std::tuple<int, std::string, bool> >& questList);
|
||||
void processQuestLine(int questId, const std::vector<std::tuple<std::string, std::string> >& questMissions);
|
||||
|
||||
// modal dialogs >= 970
|
||||
void processModalDialog(uint32 id, std::string title, std::string message, int enterId, std::string enterText, int escapeId, std::string escapeText, std::vector<std::tuple<int, std::string> > choiceList);
|
||||
|
||||
friend class ProtocolGame;
|
||||
friend class Map;
|
||||
|
||||
public:
|
||||
// login related
|
||||
void loginWorld(const std::string& account, const std::string& password, const std::string& worldName, const std::string& worldHost, int worldPort, const std::string& characterName);
|
||||
void cancelLogin();
|
||||
void forceLogout();
|
||||
void safeLogout();
|
||||
|
||||
// walk related
|
||||
bool walk(Otc::Direction direction);
|
||||
void autoWalk(std::vector<Otc::Direction> dirs);
|
||||
void forceWalk(Otc::Direction direction);
|
||||
void turn(Otc::Direction direction);
|
||||
void stop();
|
||||
|
||||
// item related
|
||||
void look(const ThingPtr& thing);
|
||||
void move(const ThingPtr &thing, const Position& toPos, int count);
|
||||
void moveToParentContainer(const ThingPtr& thing, int count);
|
||||
void rotate(const ThingPtr& thing);
|
||||
void use(const ThingPtr& thing);
|
||||
void useWith(const ItemPtr& fromThing, const ThingPtr& toThing);
|
||||
void useInventoryItem(int itemId);
|
||||
void useInventoryItemWith(int itemId, const ThingPtr& toThing);
|
||||
|
||||
// container related
|
||||
void open(const ItemPtr& item, const ContainerPtr& previousContainer);
|
||||
void openParent(const ContainerPtr& container);
|
||||
void close(const ContainerPtr& container);
|
||||
void refreshContainer(const ContainerPtr& container);
|
||||
|
||||
// attack/follow related
|
||||
void attack(CreaturePtr creature);
|
||||
void cancelAttack() { attack(nullptr); }
|
||||
void follow(CreaturePtr creature);
|
||||
void cancelFollow() { follow(nullptr); }
|
||||
void cancelAttackAndFollow();
|
||||
|
||||
// talk related
|
||||
void talk(const std::string& message);
|
||||
void talkChannel(Otc::MessageMode mode, int channelId, const std::string& message);
|
||||
void talkPrivate(Otc::MessageMode mode, const std::string& receiver, const std::string& message);
|
||||
|
||||
// channel related
|
||||
void openPrivateChannel(const std::string& receiver);
|
||||
void requestChannels();
|
||||
void joinChannel(int channelId);
|
||||
void leaveChannel(int channelId);
|
||||
void closeNpcChannel();
|
||||
void openOwnChannel();
|
||||
void inviteToOwnChannel(const std::string& name);
|
||||
void excludeFromOwnChannel(const std::string& name);
|
||||
|
||||
// party related
|
||||
void partyInvite(int creatureId);
|
||||
void partyJoin(int creatureId);
|
||||
void partyRevokeInvitation(int creatureId);
|
||||
void partyPassLeadership(int creatureId);
|
||||
void partyLeave();
|
||||
void partyShareExperience(bool active);
|
||||
|
||||
// outfit related
|
||||
void requestOutfit();
|
||||
void changeOutfit(const Outfit& outfit);
|
||||
|
||||
// vip related
|
||||
void addVip(const std::string& name);
|
||||
void removeVip(int playerId);
|
||||
|
||||
// fight modes related
|
||||
void setChaseMode(Otc::ChaseModes chaseMode);
|
||||
void setFightMode(Otc::FightModes fightMode);
|
||||
void setSafeFight(bool on);
|
||||
Otc::ChaseModes getChaseMode() { return m_chaseMode; }
|
||||
Otc::FightModes getFightMode() { return m_fightMode; }
|
||||
bool isSafeFight() { return m_safeFight; }
|
||||
|
||||
// npc trade related
|
||||
void inspectNpcTrade(const ItemPtr& item);
|
||||
void buyItem(const ItemPtr& item, int amount, bool ignoreCapacity, bool buyWithBackpack);
|
||||
void sellItem(const ItemPtr& item, int amount, bool ignoreEquipped);
|
||||
void closeNpcTrade();
|
||||
|
||||
// player trade related
|
||||
void requestTrade(const ItemPtr& item, const CreaturePtr& creature);
|
||||
void inspectTrade(bool counterOffer, int index);
|
||||
void acceptTrade();
|
||||
void rejectTrade();
|
||||
|
||||
// house window and editable items related
|
||||
void editText(uint id, const std::string& text);
|
||||
void editList(uint id, int doorId, const std::string& text);
|
||||
|
||||
// reports
|
||||
void reportBug(const std::string& comment);
|
||||
void reportRuleViolation(const std::string& target, int reason, int action, const std::string& comment, const std::string& statement, int statementId, bool ipBanishment);
|
||||
void debugReport(const std::string& a, const std::string& b, const std::string& c, const std::string& d);
|
||||
|
||||
// questlog related
|
||||
void requestQuestLog();
|
||||
void requestQuestLine(int questId);
|
||||
|
||||
// 870 only
|
||||
void equipItem(const ItemPtr& item);
|
||||
void mount(bool mount);
|
||||
|
||||
// 910 only
|
||||
void requestItemInfo(const ItemPtr& item, int index);
|
||||
|
||||
// >= 970 modal dialog
|
||||
void answerModalDialog(int dialog, int button, int choice);
|
||||
|
||||
//void reportRuleViolation2();
|
||||
void ping();
|
||||
|
||||
// dynamic support for game features
|
||||
void enableFeature(Otc::GameFeature feature) { m_features.set(feature, true); }
|
||||
void disableFeature(Otc::GameFeature feature) { m_features.set(feature, false); }
|
||||
void setFeature(Otc::GameFeature feature, bool enabled) { m_features.set(feature, enabled); }
|
||||
bool getFeature(Otc::GameFeature feature) { return m_features.test(feature); }
|
||||
|
||||
void setProtocolVersion(int version);
|
||||
int getProtocolVersion() { return m_protocolVersion; }
|
||||
|
||||
void setClientVersion(int version);
|
||||
int getClientVersion() { return m_clientVersion; }
|
||||
|
||||
bool canPerformGameAction();
|
||||
bool checkBotProtection();
|
||||
|
||||
bool isOnline() { return m_online; }
|
||||
bool isDead() { return m_dead; }
|
||||
bool isAttacking() { return !!m_attackingCreature; }
|
||||
bool isFollowing() { return !!m_followingCreature; }
|
||||
|
||||
int getPing() { return m_ping; }
|
||||
ContainerPtr getContainer(int index) { return m_containers[index]; }
|
||||
std::map<int, ContainerPtr> getContainers() { return m_containers; }
|
||||
std::map<int, Vip> getVips() { return m_vips; }
|
||||
CreaturePtr getAttackingCreature() { return m_attackingCreature; }
|
||||
CreaturePtr getFollowingCreature() { return m_followingCreature; }
|
||||
void setServerBeat(int beat) { m_serverBeat = beat; }
|
||||
int getServerBeat() { return m_serverBeat; }
|
||||
void setCanReportBugs(bool enable) { m_canReportBugs = enable; }
|
||||
bool canReportBugs() { return m_canReportBugs; }
|
||||
LocalPlayerPtr getLocalPlayer() { return m_localPlayer; }
|
||||
ProtocolGamePtr getProtocolGame() { return m_protocolGame; }
|
||||
std::string getCharacterName() { return m_characterName; }
|
||||
std::string getWorldName() { return m_worldName; }
|
||||
std::vector<uint8> getGMActions() { return m_gmActions; }
|
||||
|
||||
std::string formatCreatureName(const std::string &name);
|
||||
int findEmptyContainerId();
|
||||
|
||||
protected:
|
||||
void enableBotCall() { m_denyBotCall = false; }
|
||||
void disableBotCall() { m_denyBotCall = true; }
|
||||
|
||||
private:
|
||||
void setAttackingCreature(const CreaturePtr& creature);
|
||||
void setFollowingCreature(const CreaturePtr& creature);
|
||||
|
||||
LocalPlayerPtr m_localPlayer;
|
||||
CreaturePtr m_attackingCreature;
|
||||
CreaturePtr m_followingCreature;
|
||||
ProtocolGamePtr m_protocolGame;
|
||||
std::map<int, ContainerPtr> m_containers;
|
||||
std::map<int, Vip> m_vips;
|
||||
|
||||
bool m_online;
|
||||
bool m_denyBotCall;
|
||||
bool m_dead;
|
||||
int m_serverBeat;
|
||||
int m_ping;
|
||||
uint m_seq;
|
||||
Otc::FightModes m_fightMode;
|
||||
Otc::ChaseModes m_chaseMode;
|
||||
Otc::Direction m_lastWalkDir;
|
||||
bool m_safeFight;
|
||||
bool m_canReportBugs;
|
||||
std::vector<uint8> m_gmActions;
|
||||
std::string m_characterName;
|
||||
std::string m_worldName;
|
||||
std::bitset<Otc::LastGameFeature> m_features;
|
||||
ScheduledEventPtr m_pingEvent;
|
||||
ScheduledEventPtr m_walkEvent;
|
||||
int m_protocolVersion;
|
||||
int m_clientVersion;
|
||||
};
|
||||
|
||||
extern Game g_game;
|
||||
|
||||
#endif
|
||||
32
src/client/global.h
Normal file
32
src/client/global.h
Normal file
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright (c) 2010-2013 OTClient <https://github.com/edubart/otclient>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef OTCLIENT_GLOBAL_H
|
||||
#define OTCLIENT_GLOBAL_H
|
||||
|
||||
#include <framework/global.h>
|
||||
|
||||
// widely used headers
|
||||
#include "const.h"
|
||||
#include "position.h"
|
||||
|
||||
#endif
|
||||
163
src/client/houses.cpp
Normal file
163
src/client/houses.cpp
Normal file
@@ -0,0 +1,163 @@
|
||||
/*
|
||||
* Copyright (c) 2010-2013 OTClient <https://github.com/edubart/otclient>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "map.h"
|
||||
|
||||
#include <framework/core/resourcemanager.h>
|
||||
|
||||
HouseManager g_houses;
|
||||
|
||||
House::House()
|
||||
{
|
||||
m_nullTile = TilePtr(new Tile(Position()));
|
||||
}
|
||||
|
||||
House::House(uint32 hId, const std::string &name, const Position &pos)
|
||||
{
|
||||
m_nullTile = TilePtr(new Tile(Position()));
|
||||
setId(hId);
|
||||
setName(name);
|
||||
if(pos.isValid())
|
||||
setEntry(pos);
|
||||
}
|
||||
|
||||
void House::setTile(const TilePtr& tile)
|
||||
{
|
||||
tile->setFlags(TILESTATE_HOUSE);
|
||||
m_tiles.insert(std::make_pair(tile->getPosition(), tile));
|
||||
}
|
||||
|
||||
const TilePtr& House::getTile(const Position& position)
|
||||
{
|
||||
TileMap::const_iterator iter = m_tiles.find(position);
|
||||
if(iter != m_tiles.end())
|
||||
return iter->second;
|
||||
return m_nullTile;
|
||||
}
|
||||
|
||||
void House::load(const TiXmlElement *elem)
|
||||
{
|
||||
std::string name = elem->Attribute("name");
|
||||
if(name.empty())
|
||||
name = stdext::format("Unnamed house #%lu", getId());
|
||||
|
||||
setName(name);
|
||||
setRent(elem->readType<uint32>("rent"));
|
||||
setSize(elem->readType<uint32>("size"));
|
||||
setTownId(elem->readType<uint32>("townid"));
|
||||
m_isGuildHall = elem->readType<bool>("guildhall");
|
||||
setEntry(elem->readPos("entry"));
|
||||
}
|
||||
|
||||
void House::save(TiXmlElement*& elem)
|
||||
{
|
||||
elem = new TiXmlElement("house");
|
||||
|
||||
elem->SetAttribute("name", getName());
|
||||
elem->SetAttribute("houseid", getId());
|
||||
|
||||
Position entry = getEntry();
|
||||
elem->SetAttribute("entryx", entry.x);
|
||||
elem->SetAttribute("entryy", entry.y);
|
||||
elem->SetAttribute("entryz", entry.z);
|
||||
|
||||
elem->SetAttribute("rent", getRent());
|
||||
elem->SetAttribute("townid", getTownId());
|
||||
elem->SetAttribute("size", getSize());
|
||||
elem->SetAttribute("guildhall", (int)m_isGuildHall);
|
||||
}
|
||||
|
||||
HouseManager::HouseManager()
|
||||
{
|
||||
m_nullHouse = HousePtr(new House);
|
||||
}
|
||||
|
||||
void HouseManager::addHouse(const HousePtr& house)
|
||||
{
|
||||
if(findHouse(house->getId()) == m_houses.end())
|
||||
m_houses.push_back(house);
|
||||
}
|
||||
|
||||
void HouseManager::removeHouse(uint32 houseId)
|
||||
{
|
||||
auto it = findHouse(houseId);
|
||||
if(it != m_houses.end())
|
||||
m_houses.erase(it);
|
||||
}
|
||||
|
||||
const HousePtr& HouseManager::getHouse(uint32 houseId)
|
||||
{
|
||||
auto it = std::find_if(m_houses.begin(), m_houses.end(),
|
||||
[=] (const HousePtr& house) -> bool { return house->getId() == houseId; });
|
||||
return it != m_houses.end() ? *it : m_nullHouse;
|
||||
}
|
||||
|
||||
void HouseManager::load(const std::string& fileName)
|
||||
{
|
||||
TiXmlDocument doc;
|
||||
doc.Parse(g_resources.loadFile(fileName).c_str());
|
||||
if(doc.Error())
|
||||
stdext::throw_exception(stdext::format("failed to load '%s': %s (House XML)", fileName, doc.ErrorDesc()));
|
||||
|
||||
TiXmlElement *root = doc.FirstChildElement();
|
||||
if(!root || root->ValueTStr() != "houses")
|
||||
stdext::throw_exception("invalid root tag name");
|
||||
|
||||
for(TiXmlElement *elem = root->FirstChildElement(); elem; elem = elem->NextSiblingElement()) {
|
||||
if(elem->ValueTStr() != "house")
|
||||
stdext::throw_exception("invalid house tag.");
|
||||
|
||||
uint32 houseId = elem->readType<uint32>("houseid");
|
||||
HousePtr house = getHouse(houseId);
|
||||
if(!house)
|
||||
house = HousePtr(new House(houseId)), addHouse(house);
|
||||
|
||||
house->load(elem);
|
||||
}
|
||||
}
|
||||
|
||||
void HouseManager::save(const std::string& fileName)
|
||||
{
|
||||
TiXmlDocument doc;
|
||||
doc.SetTabSize(2);
|
||||
|
||||
TiXmlDeclaration* decl = new TiXmlDeclaration("1.0", "UTF-8", "");
|
||||
doc.LinkEndChild(decl);
|
||||
|
||||
TiXmlElement* root = new TiXmlElement("houses");
|
||||
doc.LinkEndChild(root);
|
||||
|
||||
for(auto house : m_houses) {
|
||||
TiXmlElement *elem;
|
||||
house->save(elem);
|
||||
root->LinkEndChild(elem);
|
||||
}
|
||||
|
||||
if(!doc.SaveFile(fileName))
|
||||
stdext::throw_exception(stdext::format("failed to save houses XML %s: %s", fileName, doc.ErrorDesc()));
|
||||
}
|
||||
|
||||
HouseList::iterator HouseManager::findHouse(uint32 houseId)
|
||||
{
|
||||
return std::find_if(m_houses.begin(), m_houses.end(),
|
||||
[=] (const HousePtr& house) -> bool { return house->getId() == houseId; });
|
||||
}
|
||||
105
src/client/houses.h
Normal file
105
src/client/houses.h
Normal file
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
* Copyright (c) 2010-2013 OTClient <https://github.com/edubart/otclient>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef HOUSES_H
|
||||
#define HOUSES_H
|
||||
|
||||
#include "declarations.h"
|
||||
#include "tile.h"
|
||||
|
||||
#include <framework/luaengine/luaobject.h>
|
||||
|
||||
enum HouseAttr : uint8
|
||||
{
|
||||
HouseAttrId,
|
||||
HouseAttrName,
|
||||
HouseAttrTown,
|
||||
HouseAttrEntry,
|
||||
HouseAttrSize,
|
||||
HouseAttrRent
|
||||
};
|
||||
|
||||
class House : public LuaObject
|
||||
{
|
||||
public:
|
||||
House();
|
||||
House(uint32 hId, const std::string& name = "", const Position& pos=Position());
|
||||
~House() { m_tiles.clear(); m_nullTile = nullptr; }
|
||||
|
||||
void setTile(const TilePtr& tile);
|
||||
const TilePtr& getTile(const Position& pos);
|
||||
|
||||
void setName(const std::string& name) { m_attribs.set(HouseAttrName, name); }
|
||||
std::string getName() { return m_attribs.get<std::string>(HouseAttrName); }
|
||||
|
||||
void setId(uint32 hId) { m_attribs.set(HouseAttrId, hId); }
|
||||
uint32 getId() { return m_attribs.get<uint32>(HouseAttrId); }
|
||||
|
||||
void setTownId(uint32 tid) { m_attribs.set(HouseAttrTown, tid); }
|
||||
uint32 getTownId() { return m_attribs.get<uint32>(HouseAttrTown); }
|
||||
|
||||
void setSize(uint32 s) { m_attribs.set(HouseAttrSize, s); }
|
||||
uint32 getSize() { return m_attribs.get<uint32>(HouseAttrSize); }
|
||||
|
||||
void setRent(uint32 r) { m_attribs.set(HouseAttrRent, r); }
|
||||
uint32 getRent() { return m_attribs.get<uint32>(HouseAttrRent); }
|
||||
|
||||
void setEntry(const Position& p) { m_attribs.set(HouseAttrEntry, p); }
|
||||
Position getEntry() { return m_attribs.get<Position>(HouseAttrEntry); }
|
||||
|
||||
protected:
|
||||
void load(const TiXmlElement* elem);
|
||||
void save(TiXmlElement*& elem);
|
||||
|
||||
private:
|
||||
stdext::packed_storage<uint8> m_attribs;
|
||||
TileMap m_tiles;
|
||||
TilePtr m_nullTile;
|
||||
stdext::boolean<false> m_isGuildHall;
|
||||
|
||||
friend class HouseManager;
|
||||
};
|
||||
|
||||
class HouseManager {
|
||||
public:
|
||||
HouseManager();
|
||||
|
||||
void addHouse(const HousePtr& house);
|
||||
void removeHouse(uint32 houseId);
|
||||
HouseList getHouseList() { return m_houses; }
|
||||
const HousePtr& getHouse(uint32 houseId);
|
||||
void clear() { m_houses.clear(); m_nullHouse = nullptr; }
|
||||
|
||||
void load(const std::string& fileName);
|
||||
void save(const std::string& fileName);
|
||||
|
||||
private:
|
||||
HouseList m_houses;
|
||||
HousePtr m_nullHouse;
|
||||
|
||||
protected:
|
||||
HouseList::iterator findHouse(uint32 houseId);
|
||||
};
|
||||
|
||||
extern HouseManager g_houses;
|
||||
|
||||
#endif
|
||||
369
src/client/item.cpp
Normal file
369
src/client/item.cpp
Normal file
@@ -0,0 +1,369 @@
|
||||
/*
|
||||
* Copyright (c) 2010-2013 OTClient <https://github.com/edubart/otclient>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "item.h"
|
||||
#include "thingtypemanager.h"
|
||||
#include "spritemanager.h"
|
||||
#include "thing.h"
|
||||
#include "tile.h"
|
||||
#include "shadermanager.h"
|
||||
#include "container.h"
|
||||
#include "map.h"
|
||||
#include "houses.h"
|
||||
#include "game.h"
|
||||
|
||||
#include <framework/core/clock.h>
|
||||
#include <framework/core/eventdispatcher.h>
|
||||
#include <framework/graphics/graphics.h>
|
||||
#include <framework/core/filestream.h>
|
||||
#include <framework/core/binarytree.h>
|
||||
|
||||
Item::Item() :
|
||||
m_clientId(0),
|
||||
m_serverId(0),
|
||||
m_countOrSubType(1)
|
||||
{
|
||||
}
|
||||
|
||||
ItemPtr Item::create(int id)
|
||||
{
|
||||
ItemPtr item(new Item);
|
||||
item->setId(id);
|
||||
return item;
|
||||
}
|
||||
|
||||
ItemPtr Item::createFromOtb(int id)
|
||||
{
|
||||
ItemPtr item(new Item);
|
||||
item->setOtbId(id);
|
||||
return item;
|
||||
}
|
||||
|
||||
void Item::draw(const Point& dest, float scaleFactor, bool animate, LightView *lightView)
|
||||
{
|
||||
if(m_clientId == 0)
|
||||
return;
|
||||
|
||||
// determine animation phase
|
||||
int animationPhase = calculateAnimationPhase(animate);
|
||||
|
||||
// determine x,y,z patterns
|
||||
int xPattern = 0, yPattern = 0, zPattern = 0;
|
||||
calculatePatterns(xPattern, yPattern, zPattern);
|
||||
|
||||
rawGetThingType()->draw(dest, scaleFactor, 0, xPattern, yPattern, zPattern, animationPhase, lightView);
|
||||
}
|
||||
|
||||
void Item::setId(uint32 id)
|
||||
{
|
||||
if(!g_things.isValidDatId(id, ThingCategoryItem))
|
||||
id = 0;
|
||||
m_serverId = g_things.findItemTypeByClientId(id)->getServerId();
|
||||
m_clientId = id;
|
||||
}
|
||||
|
||||
void Item::setOtbId(uint16 id)
|
||||
{
|
||||
if(!g_things.isValidOtbId(id))
|
||||
id = 0;
|
||||
auto itemType = g_things.getItemType(id);
|
||||
m_serverId = id;
|
||||
|
||||
id = itemType->getClientId();
|
||||
if(!g_things.isValidDatId(id, ThingCategoryItem))
|
||||
id = 0;
|
||||
m_clientId = id;
|
||||
}
|
||||
|
||||
bool Item::isValid()
|
||||
{
|
||||
return g_things.isValidDatId(m_clientId, ThingCategoryItem);
|
||||
}
|
||||
|
||||
void Item::unserializeItem(const BinaryTreePtr &in)
|
||||
{
|
||||
try {
|
||||
while(in->canRead()) {
|
||||
int attrib = in->getU8();
|
||||
if(attrib == 0)
|
||||
break;
|
||||
|
||||
switch(attrib) {
|
||||
case ATTR_COUNT:
|
||||
case ATTR_RUNE_CHARGES:
|
||||
setCount(in->getU8());
|
||||
break;
|
||||
case ATTR_CHARGES:
|
||||
setCount(in->getU16());
|
||||
break;
|
||||
case ATTR_HOUSEDOORID:
|
||||
case ATTR_SCRIPTPROTECTED:
|
||||
case ATTR_DUALWIELD:
|
||||
case ATTR_DECAYING_STATE:
|
||||
m_attribs.set(attrib, in->getU8());
|
||||
break;
|
||||
case ATTR_ACTION_ID:
|
||||
case ATTR_UNIQUE_ID:
|
||||
case ATTR_DEPOT_ID:
|
||||
m_attribs.set(attrib, in->getU16());
|
||||
break;
|
||||
case ATTR_CONTAINER_ITEMS:
|
||||
case ATTR_ATTACK:
|
||||
case ATTR_EXTRAATTACK:
|
||||
case ATTR_DEFENSE:
|
||||
case ATTR_EXTRADEFENSE:
|
||||
case ATTR_ARMOR:
|
||||
case ATTR_ATTACKSPEED:
|
||||
case ATTR_HITCHANCE:
|
||||
case ATTR_DURATION:
|
||||
case ATTR_WRITTENDATE:
|
||||
case ATTR_SLEEPERGUID:
|
||||
case ATTR_SLEEPSTART:
|
||||
case ATTR_ATTRIBUTE_MAP:
|
||||
m_attribs.set(attrib, in->getU32());
|
||||
break;
|
||||
case ATTR_TELE_DEST: {
|
||||
Position pos;
|
||||
pos.x = in->getU16();
|
||||
pos.y = in->getU16();
|
||||
pos.z = in->getU8();
|
||||
m_attribs.set(attrib, pos);
|
||||
break;
|
||||
}
|
||||
case ATTR_NAME:
|
||||
case ATTR_TEXT:
|
||||
case ATTR_DESC:
|
||||
case ATTR_ARTICLE:
|
||||
case ATTR_WRITTENBY:
|
||||
m_attribs.set(attrib, in->getString());
|
||||
break;
|
||||
default:
|
||||
stdext::throw_exception(stdext::format("invalid item attribute %d", attrib));
|
||||
}
|
||||
}
|
||||
} catch(stdext::exception& e) {
|
||||
g_logger.error(stdext::format("Failed to unserialize OTBM item: %s", e.what()));
|
||||
}
|
||||
}
|
||||
|
||||
void Item::serializeItem(const OutputBinaryTreePtr& out)
|
||||
{
|
||||
out->startNode(OTBM_ITEM);
|
||||
out->addU16(getServerId());
|
||||
|
||||
out->addU8(ATTR_COUNT);
|
||||
out->addU8(getCount());
|
||||
|
||||
out->addU8(ATTR_CHARGES);
|
||||
out->addU16(getCountOrSubType());
|
||||
|
||||
Position dest = m_attribs.get<Position>(ATTR_TELE_DEST);
|
||||
if(dest.isValid()) {
|
||||
out->addU8(ATTR_TELE_DEST);
|
||||
out->addPos(dest);
|
||||
}
|
||||
|
||||
if(isDepot()) {
|
||||
out->addU8(ATTR_DEPOT_ID);
|
||||
out->addU16(getDepotId());
|
||||
}
|
||||
|
||||
uint16 aid = m_attribs.get<uint16>(ATTR_ACTION_ID);
|
||||
uint16 uid = m_attribs.get<uint16>(ATTR_UNIQUE_ID);
|
||||
if(aid) {
|
||||
out->addU8(ATTR_ACTION_ID);
|
||||
out->addU16(aid);
|
||||
}
|
||||
|
||||
if(uid) {
|
||||
out->addU8(ATTR_UNIQUE_ID);
|
||||
out->addU16(uid);
|
||||
}
|
||||
|
||||
out->endNode();
|
||||
if(!m_containerItems.empty()) {
|
||||
for(auto c : m_containerItems)
|
||||
c->serializeItem(out);
|
||||
}
|
||||
}
|
||||
|
||||
int Item::getSubType()
|
||||
{
|
||||
if(isSplash() || isFluidContainer())
|
||||
return m_countOrSubType;
|
||||
if(g_game.getProtocolVersion() >= 900)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int Item::getCount()
|
||||
{
|
||||
if(isStackable())
|
||||
return m_countOrSubType;
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool Item::isMoveable()
|
||||
{
|
||||
return !rawGetThingType()->isNotMoveable();
|
||||
}
|
||||
|
||||
bool Item::isGround()
|
||||
{
|
||||
return rawGetThingType()->isGround();
|
||||
}
|
||||
|
||||
ItemPtr Item::clone()
|
||||
{
|
||||
ItemPtr item = ItemPtr(new Item);
|
||||
*(item.get()) = *this;
|
||||
return item;
|
||||
}
|
||||
|
||||
void Item::calculatePatterns(int& xPattern, int& yPattern, int& zPattern)
|
||||
{
|
||||
if(isStackable() && getNumPatternX() == 4 && getNumPatternY() == 2) {
|
||||
if(m_countOrSubType <= 0) {
|
||||
xPattern = 0;
|
||||
yPattern = 0;
|
||||
} else if(m_countOrSubType < 5) {
|
||||
xPattern = m_countOrSubType-1;
|
||||
yPattern = 0;
|
||||
} else if(m_countOrSubType < 10) {
|
||||
xPattern = 0;
|
||||
yPattern = 1;
|
||||
} else if(m_countOrSubType < 25) {
|
||||
xPattern = 1;
|
||||
yPattern = 1;
|
||||
} else if(m_countOrSubType < 50) {
|
||||
xPattern = 2;
|
||||
yPattern = 1;
|
||||
} else {
|
||||
xPattern = 3;
|
||||
yPattern = 1;
|
||||
}
|
||||
} else if(isHangable()) {
|
||||
const TilePtr& tile = getTile();
|
||||
if(tile) {
|
||||
if(tile->mustHookSouth())
|
||||
xPattern = getNumPatternX() >= 2 ? 1 : 0;
|
||||
else if(tile->mustHookEast())
|
||||
xPattern = getNumPatternX() >= 3 ? 2 : 0;
|
||||
}
|
||||
} else if(isSplash() || isFluidContainer()) {
|
||||
int color = Otc::FluidTransparent;
|
||||
switch(m_countOrSubType) {
|
||||
case Otc::FluidNone:
|
||||
color = Otc::FluidTransparent;
|
||||
break;
|
||||
case Otc::FluidWater:
|
||||
color = Otc::FluidBlue;
|
||||
break;
|
||||
case Otc::FluidMana:
|
||||
color = Otc::FluidPurple;
|
||||
break;
|
||||
case Otc::FluidBeer:
|
||||
color = Otc::FluidBrown;
|
||||
break;
|
||||
case Otc::FluidOil:
|
||||
color = Otc::FluidBrown;
|
||||
break;
|
||||
case Otc::FluidBlood:
|
||||
color = Otc::FluidRed;
|
||||
break;
|
||||
case Otc::FluidSlime:
|
||||
color = Otc::FluidGreen;
|
||||
break;
|
||||
case Otc::FluidMud:
|
||||
color = Otc::FluidBrown;
|
||||
break;
|
||||
case Otc::FluidLemonade:
|
||||
color = Otc::FluidYellow;
|
||||
break;
|
||||
case Otc::FluidMilk:
|
||||
color = Otc::FluidWhite;
|
||||
break;
|
||||
case Otc::FluidWine:
|
||||
color = Otc::FluidPurple;
|
||||
break;
|
||||
case Otc::FluidHealth:
|
||||
color = Otc::FluidRed;
|
||||
break;
|
||||
case Otc::FluidUrine:
|
||||
color = Otc::FluidYellow;
|
||||
break;
|
||||
case Otc::FluidRum:
|
||||
color = Otc::FluidBrown;
|
||||
break;
|
||||
case Otc::FluidFruidJuice:
|
||||
color = Otc::FluidYellow;
|
||||
break;
|
||||
case Otc::FluidCoconutMilk:
|
||||
color = Otc::FluidWhite;
|
||||
break;
|
||||
case Otc::FluidTea:
|
||||
color = Otc::FluidBrown;
|
||||
break;
|
||||
case Otc::FluidMead:
|
||||
color = Otc::FluidBrown;
|
||||
break;
|
||||
default:
|
||||
color = Otc::FluidTransparent;
|
||||
break;
|
||||
}
|
||||
|
||||
xPattern = (color % 4) % getNumPatternX();
|
||||
yPattern = (color / 4) % getNumPatternY();
|
||||
} else if(isGround() || isOnBottom()) {
|
||||
xPattern = m_position.x % getNumPatternX();
|
||||
yPattern = m_position.y % getNumPatternY();
|
||||
zPattern = m_position.z % getNumPatternZ();
|
||||
}
|
||||
}
|
||||
|
||||
int Item::calculateAnimationPhase(bool animate)
|
||||
{
|
||||
if(getAnimationPhases() > 1) {
|
||||
if(animate)
|
||||
return (g_clock.millis() % (Otc::ITEM_TICKS_PER_FRAME * getAnimationPhases())) / Otc::ITEM_TICKS_PER_FRAME;
|
||||
else
|
||||
return getAnimationPhases()-1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Item::getExactSize(int layer, int xPattern, int yPattern, int zPattern, int animationPhase)
|
||||
{
|
||||
calculatePatterns(xPattern, yPattern, zPattern);
|
||||
animationPhase = calculateAnimationPhase(true);
|
||||
return Thing::getExactSize(0, xPattern, yPattern, zPattern, animationPhase);
|
||||
}
|
||||
|
||||
const ThingTypePtr& Item::getThingType()
|
||||
{
|
||||
return g_things.getThingType(m_clientId, ThingCategoryItem);
|
||||
}
|
||||
|
||||
ThingType* Item::rawGetThingType()
|
||||
{
|
||||
return g_things.rawGetThingType(m_clientId, ThingCategoryItem);
|
||||
}
|
||||
144
src/client/item.h
Normal file
144
src/client/item.h
Normal file
@@ -0,0 +1,144 @@
|
||||
/*
|
||||
* Copyright (c) 2010-2013 OTClient <https://github.com/edubart/otclient>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef ITEM_H
|
||||
#define ITEM_H
|
||||
|
||||
#include <framework/global.h>
|
||||
#include "thing.h"
|
||||
#include "effect.h"
|
||||
#include "itemtype.h"
|
||||
|
||||
enum ItemAttr : uint8
|
||||
{
|
||||
ATTR_END = 0,
|
||||
//ATTR_DESCRIPTION = 1,
|
||||
//ATTR_EXT_FILE = 2,
|
||||
ATTR_TILE_FLAGS = 3,
|
||||
ATTR_ACTION_ID = 4,
|
||||
ATTR_UNIQUE_ID = 5,
|
||||
ATTR_TEXT = 6,
|
||||
ATTR_DESC = 7,
|
||||
ATTR_TELE_DEST = 8,
|
||||
ATTR_ITEM = 9,
|
||||
ATTR_DEPOT_ID = 10,
|
||||
//ATTR_EXT_SPAWN_FILE = 11,
|
||||
ATTR_RUNE_CHARGES = 12,
|
||||
//ATTR_EXT_HOUSE_FILE = 13,
|
||||
ATTR_HOUSEDOORID = 14,
|
||||
ATTR_COUNT = 15,
|
||||
ATTR_DURATION = 16,
|
||||
ATTR_DECAYING_STATE = 17,
|
||||
ATTR_WRITTENDATE = 18,
|
||||
ATTR_WRITTENBY = 19,
|
||||
ATTR_SLEEPERGUID = 20,
|
||||
ATTR_SLEEPSTART = 21,
|
||||
ATTR_CHARGES = 22,
|
||||
ATTR_CONTAINER_ITEMS = 23,
|
||||
ATTR_NAME = 30,
|
||||
ATTR_PLURALNAME = 31,
|
||||
ATTR_ATTACK = 33,
|
||||
ATTR_EXTRAATTACK = 34,
|
||||
ATTR_DEFENSE = 35,
|
||||
ATTR_EXTRADEFENSE = 36,
|
||||
ATTR_ARMOR = 37,
|
||||
ATTR_ATTACKSPEED = 38,
|
||||
ATTR_HITCHANCE = 39,
|
||||
ATTR_SHOOTRANGE = 40,
|
||||
ATTR_ARTICLE = 41,
|
||||
ATTR_SCRIPTPROTECTED = 42,
|
||||
ATTR_DUALWIELD = 43,
|
||||
ATTR_ATTRIBUTE_MAP = 128
|
||||
};
|
||||
|
||||
// @bindclass
|
||||
#pragma pack(push,1) // disable memory alignment
|
||||
class Item : public Thing
|
||||
{
|
||||
public:
|
||||
Item();
|
||||
virtual ~Item() { }
|
||||
|
||||
static ItemPtr create(int id);
|
||||
static ItemPtr createFromOtb(int id);
|
||||
|
||||
void draw(const Point& dest, float scaleFactor, bool animate, LightView *lightView = nullptr);
|
||||
|
||||
void setId(uint32 id);
|
||||
void setOtbId(uint16 id);
|
||||
void setCountOrSubType(int value) { m_countOrSubType = value; }
|
||||
void setCount(int count) { m_countOrSubType = count; }
|
||||
void setSubType(int subType) { m_countOrSubType = subType; }
|
||||
|
||||
int getCountOrSubType() { return m_countOrSubType; }
|
||||
int getSubType();
|
||||
int getCount();
|
||||
uint32 getId() { return m_clientId; }
|
||||
uint16 getClientId() { return m_clientId; }
|
||||
uint16 getServerId() { return m_serverId; }
|
||||
bool isValid();
|
||||
|
||||
ItemPtr clone();
|
||||
|
||||
void unserializeItem(const BinaryTreePtr& in);
|
||||
void serializeItem(const OutputBinaryTreePtr& out);
|
||||
|
||||
void setDepotId(uint16 depotId) { m_attribs.set(ATTR_DEPOT_ID, depotId); }
|
||||
uint16 getDepotId() { return m_attribs.get<uint16>(ATTR_DEPOT_ID); }
|
||||
|
||||
void setDoorId(uint8 doorId) { m_attribs.set(ATTR_HOUSEDOORID, doorId); }
|
||||
uint8 getDoorId() { return m_attribs.get<uint8>(ATTR_HOUSEDOORID); }
|
||||
|
||||
void setActionId(uint16 actionId) { m_attribs.set(ATTR_ACTION_ID, actionId); }
|
||||
void setUniqueId(uint16 uniqueId) { m_attribs.set(ATTR_UNIQUE_ID, uniqueId); }
|
||||
|
||||
bool isDepot() { return m_attribs.has(ATTR_DEPOT_ID); }
|
||||
bool isContainer() { return m_attribs.has(ATTR_CONTAINER_ITEMS); }
|
||||
bool isDoor() { return m_attribs.has(ATTR_HOUSEDOORID); }
|
||||
bool isTeleport() { return m_attribs.has(ATTR_TELE_DEST); }
|
||||
bool isMoveable();
|
||||
bool isGround();
|
||||
|
||||
ItemPtr asItem() { return static_self_cast<Item>(); }
|
||||
bool isItem() { return true; }
|
||||
|
||||
void addContainerItem(const ItemPtr& i) { m_containerItems.push_back(i); }
|
||||
void clearContainerItems() { m_containerItems.clear(); }
|
||||
|
||||
void calculatePatterns(int& xPattern, int& yPattern, int& zPattern);
|
||||
int calculateAnimationPhase(bool animate);
|
||||
int getExactSize(int layer = 0, int xPattern = 0, int yPattern = 0, int zPattern = 0, int animationPhase = 0);
|
||||
|
||||
const ThingTypePtr& getThingType();
|
||||
ThingType *rawGetThingType();
|
||||
|
||||
private:
|
||||
uint16 m_clientId;
|
||||
uint16 m_serverId;
|
||||
uint8 m_countOrSubType;
|
||||
stdext::packed_storage<uint8> m_attribs;
|
||||
std::vector<ItemPtr> m_containerItems;
|
||||
};
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
#endif
|
||||
80
src/client/itemtype.cpp
Normal file
80
src/client/itemtype.cpp
Normal file
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Copyright (c) 2010-2013 OTClient <https://github.com/edubart/otclient>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
|
||||
#include "thingtypemanager.h"
|
||||
#include "thingtype.h"
|
||||
|
||||
#include <framework/core/filestream.h>
|
||||
#include <framework/core/binarytree.h>
|
||||
|
||||
ItemType::ItemType()
|
||||
{
|
||||
m_category = ItemCategoryInvalid;
|
||||
}
|
||||
|
||||
void ItemType::unserialize(const BinaryTreePtr& node)
|
||||
{
|
||||
m_null = false;
|
||||
|
||||
m_category = (ItemCategory)node->getU8();
|
||||
|
||||
node->getU32(); // flags
|
||||
|
||||
static uint16 lastId = 99;
|
||||
while(node->canRead()) {
|
||||
uint8 attr = node->getU8();
|
||||
if(attr == 0 || attr == 0xFF)
|
||||
break;
|
||||
|
||||
uint16 len = node->getU16();
|
||||
switch(attr) {
|
||||
case ItemTypeAttrServerId: {
|
||||
uint16 serverId = node->getU16();
|
||||
if(serverId > 20000 && serverId < 20100) {
|
||||
serverId -= 20000;
|
||||
} else if(lastId > 99 && lastId != serverId - 1) {
|
||||
|
||||
while(lastId != serverId - 1) {
|
||||
ItemTypePtr tmp(new ItemType);
|
||||
tmp->setServerId(lastId++);
|
||||
g_things.addItemType(tmp);
|
||||
}
|
||||
}
|
||||
setServerId(serverId);
|
||||
lastId = serverId;
|
||||
break;
|
||||
}
|
||||
case ItemTypeAttrClientId: {
|
||||
setClientId(node->getU16());
|
||||
break;
|
||||
}
|
||||
case ItemTypeAttrName: {
|
||||
setName(node->getString(len));
|
||||
break;
|
||||
}
|
||||
default:
|
||||
node->skip(len); // skip attribute
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
159
src/client/itemtype.h
Normal file
159
src/client/itemtype.h
Normal file
@@ -0,0 +1,159 @@
|
||||
/*
|
||||
* Copyright (c) 2010-2013 OTClient <https://github.com/edubart/otclient>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef ITEMTYPE_H
|
||||
#define ITEMTYPE_H
|
||||
|
||||
#include <framework/core/declarations.h>
|
||||
#include <framework/luaengine/luaobject.h>
|
||||
#include <framework/xml/tinyxml.h>
|
||||
|
||||
enum ItemCategory : uint8 {
|
||||
ItemCategoryInvalid = 0,
|
||||
ItemCategoryGround = 1,
|
||||
ItemCategoryContainer = 2,
|
||||
ItemCategoryWeapon = 3,
|
||||
ItemCategoryAmmunition = 4,
|
||||
ItemCategoryArmor = 5,
|
||||
ItemCategoryCharges = 6,
|
||||
ItemCategoryTeleport = 7,
|
||||
ItemCategoryMagicField = 8,
|
||||
ItemCategoryWritable = 9,
|
||||
ItemCategoryKey = 10,
|
||||
ItemCategorySplash = 11,
|
||||
ItemCategoryFluid = 12,
|
||||
ItemCategoryDoor = 13,
|
||||
ItemCategoryLast = 14
|
||||
};
|
||||
|
||||
enum ItemTypeAttr : uint8 {
|
||||
ItemTypeAttrServerId = 16,
|
||||
ItemTypeAttrClientId = 17,
|
||||
ItemTypeAttrName = 18, // deprecated
|
||||
ItemTypeAttrDesc = 19, // deprecated
|
||||
ItemTypeAttrSpeed = 20,
|
||||
ItemTypeAttrSlot = 21, // deprecated
|
||||
ItemTypeAttrMaxItems = 22, // deprecated
|
||||
ItemTypeAttrWeight = 23, // deprecated
|
||||
ItemTypeAttrWeapon = 24, // deprecated
|
||||
ItemTypeAttrAmmunition = 25, // deprecated
|
||||
ItemTypeAttrArmor = 26, // deprecated
|
||||
ItemTypeAttrMagicLevel = 27, // deprecated
|
||||
ItemTypeAttrMagicField = 28, // deprecated
|
||||
ItemTypeAttrWritable = 29, // deprecated
|
||||
ItemTypeAttrRotateTo = 30, // deprecated
|
||||
ItemTypeAttrDecay = 31, // deprecated
|
||||
ItemTypeAttrSpriteHash = 32,
|
||||
ItemTypeAttrMinimapColor = 33,
|
||||
ItemTypeAttr07 = 34,
|
||||
ItemTypeAttr08 = 35,
|
||||
ItemTypeAttrLight = 36,
|
||||
ItemTypeAttrDecay2 = 37, // deprecated
|
||||
ItemTypeAttrWeapon2 = 38, // deprecated
|
||||
ItemTypeAttrAmmunition2 = 39, // deprecated
|
||||
ItemTypeAttrArmor2 = 40, // deprecated
|
||||
ItemTypeAttrWritable2 = 41, // deprecated
|
||||
ItemTypeAttrLight2 = 42,
|
||||
ItemTypeAttrTopOrder = 43,
|
||||
ItemTypeAttrWrtiable3 = 44, // deprecated
|
||||
ItemTypeAttrLast = 45
|
||||
};
|
||||
|
||||
enum ClientVersion
|
||||
{
|
||||
ClientVersion750 = 1,
|
||||
ClientVersion755 = 2,
|
||||
ClientVersion760 = 3,
|
||||
ClientVersion770 = 3,
|
||||
ClientVersion780 = 4,
|
||||
ClientVersion790 = 5,
|
||||
ClientVersion792 = 6,
|
||||
ClientVersion800 = 7,
|
||||
ClientVersion810 = 8,
|
||||
ClientVersion811 = 9,
|
||||
ClientVersion820 = 10,
|
||||
ClientVersion830 = 11,
|
||||
ClientVersion840 = 12,
|
||||
ClientVersion841 = 13,
|
||||
ClientVersion842 = 14,
|
||||
ClientVersion850 = 15,
|
||||
ClientVersion854_OLD = 16,
|
||||
ClientVersion854 = 17,
|
||||
ClientVersion855 = 18,
|
||||
ClientVersion860_OLD = 19,
|
||||
ClientVersion860 = 20,
|
||||
ClientVersion861 = 21,
|
||||
ClientVersion862 = 22,
|
||||
ClientVersion870 = 23,
|
||||
ClientVersion871 = 24,
|
||||
ClientVersion872 = 25,
|
||||
ClientVersion873 = 26,
|
||||
ClientVersion900 = 27,
|
||||
ClientVersion910 = 28,
|
||||
ClientVersion920 = 29,
|
||||
ClientVersion940 = 30,
|
||||
ClientVersion944_V1 = 31,
|
||||
ClientVersion944_V2 = 32,
|
||||
ClientVersion944_V3 = 33,
|
||||
ClientVersion944_V4 = 34,
|
||||
ClientVersion946 = 35,
|
||||
ClientVersion950 = 36,
|
||||
ClientVersion952 = 37,
|
||||
ClientVersion953 = 38,
|
||||
ClientVersion954 = 39,
|
||||
ClientVersion960 = 40,
|
||||
ClientVersion961 = 41
|
||||
};
|
||||
|
||||
class ItemType : public LuaObject
|
||||
{
|
||||
public:
|
||||
ItemType();
|
||||
|
||||
void unserialize(const BinaryTreePtr& node);
|
||||
|
||||
void setServerId(uint16 serverId) { m_attribs.set(ItemTypeAttrServerId, serverId); }
|
||||
uint16 getServerId() { return m_attribs.get<uint16>(ItemTypeAttrServerId); }
|
||||
|
||||
void setClientId(uint16 clientId) { m_attribs.set(ItemTypeAttrClientId, clientId); }
|
||||
uint16 getClientId() { return m_attribs.get<uint16>(ItemTypeAttrClientId); }
|
||||
|
||||
void setCategory(ItemCategory category) { m_category = category; }
|
||||
ItemCategory getCategory() { return m_category; }
|
||||
|
||||
void setName(const std::string& name) { m_attribs.set(ItemTypeAttrName, name); }
|
||||
std::string getName() { return m_attribs.get<std::string>(ItemTypeAttrName); }
|
||||
|
||||
void setDesc(const std::string& desc) { m_attribs.set(ItemTypeAttrDesc, desc); }
|
||||
std::string getDesc() { return m_attribs.get<std::string>(ItemTypeAttrDesc); }
|
||||
|
||||
bool isNull() { return m_null; }
|
||||
|
||||
private:
|
||||
ItemCategory m_category;
|
||||
stdext::boolean<true> m_null;
|
||||
|
||||
stdext::dynamic_storage<uint8> m_attribs;
|
||||
};
|
||||
|
||||
#endif
|
||||
136
src/client/lightview.cpp
Normal file
136
src/client/lightview.cpp
Normal file
@@ -0,0 +1,136 @@
|
||||
/*
|
||||
* Copyright (c) 2010-2013 OTClient <https://github.com/edubart/otclient>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "lightview.h"
|
||||
#include "mapview.h"
|
||||
#include <framework/graphics/framebuffer.h>
|
||||
#include <framework/graphics/framebuffermanager.h>
|
||||
#include <framework/graphics/painter.h>
|
||||
#include <framework/graphics/image.h>
|
||||
|
||||
enum {
|
||||
MAX_LIGHT_INTENSITY = 8,
|
||||
MAX_AMBIENT_LIGHT_INTENSITY = 255
|
||||
};
|
||||
|
||||
LightView::LightView()
|
||||
{
|
||||
m_lightbuffer = g_framebuffers.createFrameBuffer();
|
||||
m_lightTexture = generateLightBubble(0.1f);
|
||||
reset();
|
||||
}
|
||||
|
||||
TexturePtr LightView::generateLightBubble(float centerFactor)
|
||||
{
|
||||
int bubbleRadius = 256;
|
||||
int centerRadius = bubbleRadius * centerFactor;
|
||||
int bubbleDiameter = bubbleRadius * 2;
|
||||
ImagePtr lightImage = ImagePtr(new Image(Size(bubbleDiameter, bubbleDiameter)));
|
||||
|
||||
for(int x = 0; x < bubbleDiameter; x++) {
|
||||
for(int y = 0; y < bubbleDiameter; y++) {
|
||||
float radius = std::sqrt((bubbleRadius - x)*(bubbleRadius - x) + (bubbleRadius - y)*(bubbleRadius - y));
|
||||
float intensity = std::max(std::min((bubbleRadius-radius)/(float)(bubbleRadius-centerRadius), 1.0f), 0.0f);
|
||||
|
||||
// light intensity varies inversely with the square of the distance
|
||||
intensity = intensity * intensity;
|
||||
uint8_t colorByte = intensity * 0xff;
|
||||
|
||||
uint8_t pixel[4] = {colorByte,colorByte,colorByte,0xff};
|
||||
lightImage->setPixel(x, y, pixel);
|
||||
}
|
||||
}
|
||||
|
||||
TexturePtr tex = TexturePtr(new Texture(lightImage, true));
|
||||
tex->setSmooth(true);
|
||||
return tex;
|
||||
}
|
||||
|
||||
void LightView::reset()
|
||||
{
|
||||
m_lightMap.clear();
|
||||
}
|
||||
|
||||
void LightView::setGlobalLight(const Light& light)
|
||||
{
|
||||
m_globalLight = light;
|
||||
}
|
||||
|
||||
void LightView::addLightSource(const Point& center, float scaleFactor, const Light& light)
|
||||
{
|
||||
int intensity = std::min<int>(light.intensity, MAX_LIGHT_INTENSITY);
|
||||
int radius = intensity * Otc::TILE_PIXELS * scaleFactor;
|
||||
|
||||
Color color = Color::from8bit(light.color);
|
||||
float brightness = 0.5f + (intensity/(float)MAX_LIGHT_INTENSITY)*0.5f;
|
||||
|
||||
color.setRed(color.rF() * brightness);
|
||||
color.setGreen(color.gF() * brightness);
|
||||
color.setBlue(color.bF() * brightness);
|
||||
|
||||
LightSource source;
|
||||
source.center = center;
|
||||
source.color = color;
|
||||
source.radius = radius;
|
||||
m_lightMap.push_back(source);
|
||||
}
|
||||
|
||||
void LightView::drawGlobalLight(const Light& light)
|
||||
{
|
||||
Color color = Color::from8bit(light.color);
|
||||
float brightness = light.intensity / (float)MAX_AMBIENT_LIGHT_INTENSITY;
|
||||
color.setRed(color.rF() * brightness);
|
||||
color.setGreen(color.gF() * brightness);
|
||||
color.setBlue(color.bF() * brightness);
|
||||
g_painter->setColor(color);
|
||||
g_painter->drawFilledRect(Rect(0,0,m_lightbuffer->getSize()));
|
||||
}
|
||||
|
||||
void LightView::drawLightSource(const Point& center, const Color& color, int radius)
|
||||
{
|
||||
// debug draw
|
||||
//radius /= 16;
|
||||
|
||||
Rect dest = Rect(center - Point(radius, radius), Size(radius*2,radius*2));
|
||||
g_painter->setColor(color);
|
||||
g_painter->drawTexturedRect(dest, m_lightTexture);
|
||||
}
|
||||
|
||||
void LightView::resize(const Size& size)
|
||||
{
|
||||
m_lightbuffer->resize(size);
|
||||
}
|
||||
|
||||
void LightView::draw(const Rect& dest, const Rect& src)
|
||||
{
|
||||
g_painter->saveAndResetState();
|
||||
m_lightbuffer->bind();
|
||||
g_painter->setCompositionMode(Painter::CompositionMode_Replace);
|
||||
drawGlobalLight(m_globalLight);
|
||||
g_painter->setCompositionMode(Painter::CompositionMode_Add);
|
||||
for(const LightSource& source : m_lightMap)
|
||||
drawLightSource(source.center, source.color, source.radius);
|
||||
m_lightbuffer->release();
|
||||
g_painter->setCompositionMode(Painter::CompositionMode_Light);
|
||||
m_lightbuffer->draw(dest, src);
|
||||
g_painter->restoreSavedState();
|
||||
}
|
||||
59
src/client/lightview.h
Normal file
59
src/client/lightview.h
Normal file
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright (c) 2010-2013 OTClient <https://github.com/edubart/otclient>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef LIGHTVIEW_H
|
||||
#define LIGHTVIEW_H
|
||||
|
||||
#include "declarations.h"
|
||||
#include <framework/graphics/declarations.h>
|
||||
#include "thingtype.h"
|
||||
|
||||
struct LightSource {
|
||||
Color color;
|
||||
Point center;
|
||||
int radius;
|
||||
};
|
||||
|
||||
class LightView : public LuaObject
|
||||
{
|
||||
public:
|
||||
LightView();
|
||||
|
||||
void reset();
|
||||
void setGlobalLight(const Light& light);
|
||||
void addLightSource(const Point& center, float scaleFactor, const Light& light);
|
||||
void resize(const Size& size);
|
||||
void draw(const Rect& dest, const Rect& src);
|
||||
|
||||
private:
|
||||
void drawGlobalLight(const Light& light);
|
||||
void drawLightSource(const Point& center, const Color& color, int radius);
|
||||
TexturePtr generateLightBubble(float centerFactor);
|
||||
|
||||
TexturePtr m_lightTexture;
|
||||
FrameBufferPtr m_lightbuffer;
|
||||
MapView* m_mapView;
|
||||
Light m_globalLight;
|
||||
std::vector<LightSource> m_lightMap;
|
||||
};
|
||||
|
||||
#endif
|
||||
517
src/client/localplayer.cpp
Normal file
517
src/client/localplayer.cpp
Normal file
@@ -0,0 +1,517 @@
|
||||
/*
|
||||
* Copyright (c) 2010-2013 OTClient <https://github.com/edubart/otclient>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "localplayer.h"
|
||||
#include "map.h"
|
||||
#include "game.h"
|
||||
#include "tile.h"
|
||||
#include <framework/core/eventdispatcher.h>
|
||||
|
||||
LocalPlayer::LocalPlayer()
|
||||
{
|
||||
m_states = 0;
|
||||
m_vocation = 0;
|
||||
m_walkLockExpiration = 0;
|
||||
m_lastWalkPing = -1;
|
||||
|
||||
m_skillsLevel.fill(-1);
|
||||
m_skillsBaseLevel.fill(-1);
|
||||
m_skillsLevelPercent.fill(-1);
|
||||
|
||||
m_health = -1;
|
||||
m_maxHealth = -1;
|
||||
m_freeCapacity = -1;
|
||||
m_experience = -1;
|
||||
m_level = -1;
|
||||
m_levelPercent = -1;
|
||||
m_mana = -1;
|
||||
m_maxMana = -1;
|
||||
m_magicLevel = -1;
|
||||
m_magicLevelPercent = -1;
|
||||
m_baseMagicLevel = -1;
|
||||
m_soul = -1;
|
||||
m_stamina = -1;
|
||||
m_baseSpeed = -1;
|
||||
m_regenerationTime = -1;
|
||||
m_offlineTrainingTime = -1;
|
||||
m_totalCapacity = -1;
|
||||
}
|
||||
|
||||
void LocalPlayer::lockWalk(int millis)
|
||||
{
|
||||
m_walkLockExpiration = std::max(m_walkLockExpiration, (ticks_t) g_clock.millis() + millis);
|
||||
}
|
||||
|
||||
bool LocalPlayer::canWalk(Otc::Direction direction)
|
||||
{
|
||||
// cannot walk while locked
|
||||
if(m_walkLockExpiration != 0 && g_clock.millis() < m_walkLockExpiration)
|
||||
return false;
|
||||
|
||||
// paralyzed
|
||||
if(m_speed == 0)
|
||||
return false;
|
||||
|
||||
// last walk is not done yet
|
||||
if(m_walkTimer.ticksElapsed() < getStepDuration())
|
||||
return false;
|
||||
|
||||
// prewalk has a timeout, because for some reason that I don't know yet the server sometimes doesn't answer the prewalk
|
||||
bool prewalkTimeouted = m_walking && m_preWalking && m_walkTimer.ticksElapsed() >= getStepDuration() + PREWALK_TIMEOUT;
|
||||
|
||||
// avoid doing more walks than wanted when receiving a lot of walks from server
|
||||
if(!m_lastPrewalkDone && m_preWalking && !prewalkTimeouted)
|
||||
return false;
|
||||
|
||||
// cannot walk while already walking
|
||||
if(m_walking && !prewalkTimeouted)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void LocalPlayer::walk(const Position& oldPos, const Position& newPos)
|
||||
{
|
||||
// a prewalk was going on
|
||||
if(m_preWalking) {
|
||||
if(m_waitingWalkPong) {
|
||||
if(newPos == m_lastPrewalkDestionation)
|
||||
m_lastWalkPing = m_walkPingTimer.ticksElapsed();
|
||||
|
||||
m_waitingWalkPong = false;
|
||||
}
|
||||
|
||||
// switch to normal walking
|
||||
m_preWalking = false;
|
||||
m_lastPrewalkDone = true;
|
||||
// if is to the last prewalk destination, updates the walk preserving the animation
|
||||
if(newPos == m_lastPrewalkDestionation) {
|
||||
updateWalk();
|
||||
// was to another direction, replace the walk
|
||||
} else
|
||||
Creature::walk(oldPos, newPos);
|
||||
}
|
||||
// no prewalk was going on, this must be an server side automated walk
|
||||
else {
|
||||
m_walkPingTimer.restart();
|
||||
m_autoWalking = true;
|
||||
if(m_autoWalkEndEvent)
|
||||
m_autoWalkEndEvent->cancel();
|
||||
|
||||
Creature::walk(oldPos, newPos);
|
||||
}
|
||||
}
|
||||
|
||||
void LocalPlayer::preWalk(Otc::Direction direction)
|
||||
{
|
||||
Position newPos = m_position.translatedToDirection(direction);
|
||||
|
||||
// avoid reanimating prewalks
|
||||
if(m_preWalking && m_lastPrewalkDestionation == newPos)
|
||||
return;
|
||||
|
||||
m_waitingWalkPong = false;
|
||||
if(m_walkPingTimer.ticksElapsed() > getStepDuration() && m_idleTimer.ticksElapsed() > getStepDuration()*2) {
|
||||
m_waitingWalkPong = true;
|
||||
m_walkPingTimer.restart();
|
||||
}
|
||||
|
||||
m_preWalking = true;
|
||||
|
||||
if(m_autoWalkEndEvent)
|
||||
m_autoWalkEndEvent->cancel();
|
||||
|
||||
// start walking to direction
|
||||
m_lastPrewalkDone = false;
|
||||
m_lastPrewalkDestionation = newPos;
|
||||
Creature::walk(m_position, newPos);
|
||||
}
|
||||
|
||||
void LocalPlayer::cancelWalk(Otc::Direction direction)
|
||||
{
|
||||
// only cancel client side walks
|
||||
if(m_walking && m_preWalking)
|
||||
stopWalk();
|
||||
|
||||
m_lastPrewalkDone = true;
|
||||
m_waitingWalkPong = false;
|
||||
m_walkPingTimer.restart();
|
||||
m_idleTimer.restart();
|
||||
|
||||
// turn to the cancel direction
|
||||
if(direction != Otc::InvalidDirection)
|
||||
setDirection(direction);
|
||||
|
||||
updateAutoWalkSteps(true);
|
||||
|
||||
callLuaField("onCancelWalk", direction);
|
||||
}
|
||||
|
||||
void LocalPlayer::updateAutoWalkSteps(bool walkFailed)
|
||||
{
|
||||
if(!m_autoWalking) {
|
||||
m_autoWalkSteps.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
if(!m_lastAutoWalkDestination.isValid()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// for now this cannot be done from lua, due to bot protection
|
||||
m_autoWalkSteps.push_back(m_lastAutoWalkDestination);
|
||||
if(m_autoWalkSteps.size() >= Otc::MAX_AUTOWALK_STEPS_RETRY || walkFailed) {
|
||||
autoWalk(m_lastAutoWalkDestination);
|
||||
}
|
||||
}
|
||||
|
||||
bool LocalPlayer::autoWalk(const Position& destination)
|
||||
{
|
||||
m_autoWalkSteps.clear();
|
||||
|
||||
m_lastAutoWalkDestination = destination;
|
||||
std::tuple<std::vector<Otc::Direction>, Otc::PathFindResult> result = g_map.findPath(m_position, destination, 127, Otc::PathFindAllowNullTiles);
|
||||
|
||||
std::vector<Otc::Direction> dirs = std::get<0>(result);
|
||||
if(dirs.size() == 0)
|
||||
return false;
|
||||
|
||||
g_game.autoWalk(dirs);
|
||||
return true;
|
||||
}
|
||||
|
||||
void LocalPlayer::stopAutoWalkUpdate()
|
||||
{
|
||||
m_lastAutoWalkDestination = Position();
|
||||
m_autoWalkSteps.clear();
|
||||
}
|
||||
|
||||
void LocalPlayer::stopWalk()
|
||||
{
|
||||
Creature::stopWalk(); // will call terminateWalk
|
||||
|
||||
m_lastPrewalkDone = true;
|
||||
m_lastPrewalkDestionation = Position();
|
||||
}
|
||||
|
||||
void LocalPlayer::updateWalkOffset(int totalPixelsWalked)
|
||||
{
|
||||
// pre walks offsets are calculated in the oposite direction
|
||||
if(m_preWalking) {
|
||||
m_walkOffset = Point(0,0);
|
||||
if(m_direction == Otc::North || m_direction == Otc::NorthEast || m_direction == Otc::NorthWest)
|
||||
m_walkOffset.y = -totalPixelsWalked;
|
||||
else if(m_direction == Otc::South || m_direction == Otc::SouthEast || m_direction == Otc::SouthWest)
|
||||
m_walkOffset.y = totalPixelsWalked;
|
||||
|
||||
if(m_direction == Otc::East || m_direction == Otc::NorthEast || m_direction == Otc::SouthEast)
|
||||
m_walkOffset.x = totalPixelsWalked;
|
||||
else if(m_direction == Otc::West || m_direction == Otc::NorthWest || m_direction == Otc::SouthWest)
|
||||
m_walkOffset.x = -totalPixelsWalked;
|
||||
} else
|
||||
Creature::updateWalkOffset(totalPixelsWalked);
|
||||
}
|
||||
|
||||
void LocalPlayer::updateWalk()
|
||||
{
|
||||
int stepDuration = getStepDuration();
|
||||
float walkTicksPerPixel = getStepDuration(true) / 32.0f;
|
||||
int totalPixelsWalked = std::min(m_walkTimer.ticksElapsed() / walkTicksPerPixel, 32.0f);
|
||||
|
||||
// update walk animation and offsets
|
||||
updateWalkAnimation(totalPixelsWalked);
|
||||
updateWalkOffset(totalPixelsWalked);
|
||||
updateWalkingTile();
|
||||
|
||||
// terminate walk only when client and server side walk are completed
|
||||
if(m_walking && !m_preWalking && m_walkTimer.ticksElapsed() >= stepDuration)
|
||||
terminateWalk();
|
||||
}
|
||||
|
||||
void LocalPlayer::terminateWalk()
|
||||
{
|
||||
Creature::terminateWalk();
|
||||
m_preWalking = false;
|
||||
m_idleTimer.restart();
|
||||
|
||||
auto self = asLocalPlayer();
|
||||
|
||||
if(m_autoWalking) {
|
||||
if(m_autoWalkEndEvent)
|
||||
m_autoWalkEndEvent->cancel();
|
||||
m_autoWalkEndEvent = g_dispatcher.scheduleEvent([self] {
|
||||
self->m_autoWalking = false;
|
||||
}, 100);
|
||||
}
|
||||
}
|
||||
|
||||
void LocalPlayer::onAppear()
|
||||
{
|
||||
Creature::onAppear();
|
||||
|
||||
// on teleports lock the walk
|
||||
if(!m_oldPosition.isInRange(m_position,1,1))
|
||||
lockWalk();
|
||||
}
|
||||
|
||||
void LocalPlayer::onPositionChange(const Position& newPos, const Position& oldPos)
|
||||
{
|
||||
Creature::onPositionChange(newPos, oldPos);
|
||||
|
||||
updateAutoWalkSteps();
|
||||
}
|
||||
|
||||
void LocalPlayer::setStates(int states)
|
||||
{
|
||||
if(m_states != states) {
|
||||
int oldStates = m_states;
|
||||
m_states = states;
|
||||
callLuaField("onStatesChange", states, oldStates);
|
||||
}
|
||||
}
|
||||
|
||||
void LocalPlayer::setSkill(Otc::Skill skill, int level, int levelPercent)
|
||||
{
|
||||
if(skill >= Otc::LastSkill) {
|
||||
g_logger.traceError("invalid skill");
|
||||
return;
|
||||
}
|
||||
|
||||
int oldLevel = m_skillsLevel[skill];
|
||||
int oldLevelPercent = m_skillsLevelPercent[skill];
|
||||
|
||||
if(level != oldLevel || levelPercent != oldLevelPercent) {
|
||||
m_skillsLevel[skill] = level;
|
||||
m_skillsLevelPercent[skill] = levelPercent;
|
||||
|
||||
callLuaField("onSkillChange", skill, level, levelPercent, oldLevel, oldLevelPercent);
|
||||
}
|
||||
}
|
||||
|
||||
void LocalPlayer::setBaseSkill(Otc::Skill skill, int baseLevel)
|
||||
{
|
||||
if(skill >= Otc::LastSkill) {
|
||||
g_logger.traceError("invalid skill");
|
||||
return;
|
||||
}
|
||||
|
||||
int oldBaseLevel = m_skillsBaseLevel[skill];
|
||||
if(baseLevel != oldBaseLevel) {
|
||||
m_skillsBaseLevel[skill] = baseLevel;
|
||||
|
||||
callLuaField("onBaseSkillChange", skill, baseLevel, oldBaseLevel);
|
||||
}
|
||||
}
|
||||
|
||||
void LocalPlayer::setHealth(double health, double maxHealth)
|
||||
{
|
||||
if(m_health != health || m_maxHealth != maxHealth) {
|
||||
double oldHealth = m_health;
|
||||
double oldMaxHealth = m_maxHealth;
|
||||
m_health = health;
|
||||
m_maxHealth = maxHealth;
|
||||
|
||||
callLuaField("onHealthChange", health, maxHealth, oldHealth, oldMaxHealth);
|
||||
|
||||
// cannot walk while dying
|
||||
if(health == 0) {
|
||||
if(isPreWalking())
|
||||
stopWalk();
|
||||
lockWalk();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LocalPlayer::setFreeCapacity(double freeCapacity)
|
||||
{
|
||||
if(m_freeCapacity != freeCapacity) {
|
||||
double oldFreeCapacity = m_freeCapacity;
|
||||
m_freeCapacity = freeCapacity;
|
||||
|
||||
callLuaField("onFreeCapacityChange", freeCapacity, oldFreeCapacity);
|
||||
}
|
||||
}
|
||||
|
||||
void LocalPlayer::setTotalCapacity(double totalCapacity)
|
||||
{
|
||||
if(m_totalCapacity != totalCapacity) {
|
||||
double oldTotalCapacity = m_totalCapacity;
|
||||
m_totalCapacity = totalCapacity;
|
||||
|
||||
callLuaField("onTotalCapacityChange", totalCapacity, oldTotalCapacity);
|
||||
}
|
||||
}
|
||||
|
||||
void LocalPlayer::setExperience(double experience)
|
||||
{
|
||||
if(m_experience != experience) {
|
||||
double oldExperience = m_experience;
|
||||
m_experience = experience;
|
||||
|
||||
callLuaField("onExperienceChange", experience, oldExperience);
|
||||
}
|
||||
}
|
||||
|
||||
void LocalPlayer::setLevel(double level, double levelPercent)
|
||||
{
|
||||
if(m_level != level || m_levelPercent != levelPercent) {
|
||||
double oldLevel = m_level;
|
||||
double oldLevelPercent = m_levelPercent;
|
||||
m_level = level;
|
||||
m_levelPercent = levelPercent;
|
||||
|
||||
callLuaField("onLevelChange", level, levelPercent, oldLevel, oldLevelPercent);
|
||||
}
|
||||
}
|
||||
|
||||
void LocalPlayer::setMana(double mana, double maxMana)
|
||||
{
|
||||
if(m_mana != mana || m_maxMana != maxMana) {
|
||||
double oldMana = m_mana;
|
||||
double oldMaxMana;
|
||||
m_mana = mana;
|
||||
m_maxMana = maxMana;
|
||||
|
||||
callLuaField("onManaChange", mana, maxMana, oldMana, oldMaxMana);
|
||||
}
|
||||
}
|
||||
|
||||
void LocalPlayer::setMagicLevel(double magicLevel, double magicLevelPercent)
|
||||
{
|
||||
if(m_magicLevel != magicLevel || m_magicLevelPercent != magicLevelPercent) {
|
||||
double oldMagicLevel = m_magicLevel;
|
||||
double oldMagicLevelPercent = m_magicLevelPercent;
|
||||
m_magicLevel = magicLevel;
|
||||
m_magicLevelPercent = magicLevelPercent;
|
||||
|
||||
callLuaField("onMagicLevelChange", magicLevel, magicLevelPercent, oldMagicLevel, oldMagicLevelPercent);
|
||||
}
|
||||
}
|
||||
|
||||
void LocalPlayer::setBaseMagicLevel(double baseMagicLevel)
|
||||
{
|
||||
if(m_baseMagicLevel != baseMagicLevel) {
|
||||
double oldBaseMagicLevel = m_baseMagicLevel;
|
||||
m_baseMagicLevel = baseMagicLevel;
|
||||
|
||||
callLuaField("onBaseMagicLevelChange", baseMagicLevel, oldBaseMagicLevel);
|
||||
}
|
||||
}
|
||||
|
||||
void LocalPlayer::setSoul(double soul)
|
||||
{
|
||||
if(m_soul != soul) {
|
||||
double oldSoul = m_soul;
|
||||
m_soul = soul;
|
||||
|
||||
callLuaField("onSoulChange", soul, oldSoul);
|
||||
}
|
||||
}
|
||||
|
||||
void LocalPlayer::setStamina(double stamina)
|
||||
{
|
||||
if(m_stamina != stamina) {
|
||||
double oldStamina = m_stamina;
|
||||
m_stamina = stamina;
|
||||
|
||||
callLuaField("onStaminaChange", stamina, oldStamina);
|
||||
}
|
||||
}
|
||||
|
||||
void LocalPlayer::setInventoryItem(Otc::InventorySlot inventory, const ItemPtr& item)
|
||||
{
|
||||
if(inventory >= Otc::LastInventorySlot) {
|
||||
g_logger.traceError("invalid slot");
|
||||
return;
|
||||
}
|
||||
|
||||
if(m_inventoryItems[inventory] != item) {
|
||||
ItemPtr oldItem = m_inventoryItems[inventory];
|
||||
m_inventoryItems[inventory] = item;
|
||||
|
||||
callLuaField("onInventoryChange", inventory, item, oldItem);
|
||||
}
|
||||
}
|
||||
|
||||
void LocalPlayer::setVocation(int vocation)
|
||||
{
|
||||
if(m_vocation != vocation) {
|
||||
int oldVocation = m_vocation;
|
||||
m_vocation = vocation;
|
||||
|
||||
callLuaField("onVocationChange", vocation, oldVocation);
|
||||
}
|
||||
}
|
||||
|
||||
void LocalPlayer::setPremium(bool premium)
|
||||
{
|
||||
if(m_premium != premium) {
|
||||
m_premium = premium;
|
||||
|
||||
callLuaField("onPremiumChange", premium);
|
||||
}
|
||||
}
|
||||
|
||||
void LocalPlayer::setBaseSpeed(double baseSpeed)
|
||||
{
|
||||
if(m_baseSpeed != baseSpeed) {
|
||||
double oldBaseSpeed = m_baseSpeed;
|
||||
m_baseSpeed = baseSpeed;
|
||||
|
||||
callLuaField("onBaseSpeedChange", baseSpeed, oldBaseSpeed);
|
||||
}
|
||||
}
|
||||
|
||||
void LocalPlayer::setRegenerationTime(double regenerationTime)
|
||||
{
|
||||
if(m_regenerationTime != regenerationTime) {
|
||||
double oldRegenerationTime = m_regenerationTime;
|
||||
m_regenerationTime = regenerationTime;
|
||||
|
||||
callLuaField("onRegenerationChange", regenerationTime, oldRegenerationTime);
|
||||
}
|
||||
}
|
||||
|
||||
void LocalPlayer::setOfflineTrainingTime(double offlineTrainingTime)
|
||||
{
|
||||
if(m_offlineTrainingTime != offlineTrainingTime) {
|
||||
double oldOfflineTrainingTime = m_offlineTrainingTime;
|
||||
m_offlineTrainingTime = offlineTrainingTime;
|
||||
|
||||
callLuaField("onOfflineTrainingChange", offlineTrainingTime, oldOfflineTrainingTime);
|
||||
}
|
||||
}
|
||||
|
||||
void LocalPlayer::setSpells(const std::vector<int>& spells)
|
||||
{
|
||||
if(m_spells != spells) {
|
||||
std::vector<int> oldSpells = m_spells;
|
||||
m_spells = spells;
|
||||
|
||||
callLuaField("onSpellsChange", spells, oldSpells);
|
||||
}
|
||||
}
|
||||
|
||||
bool LocalPlayer::hasSight(const Position& pos)
|
||||
{
|
||||
return m_position.isInRange(pos, (Otc::VISIBLE_X_TILES - 1)/2, (Otc::VISIBLE_Y_TILES - 1)/2);
|
||||
}
|
||||
169
src/client/localplayer.h
Normal file
169
src/client/localplayer.h
Normal file
@@ -0,0 +1,169 @@
|
||||
/*
|
||||
* Copyright (c) 2010-2013 OTClient <https://github.com/edubart/otclient>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef LOCALPLAYER_H
|
||||
#define LOCALPLAYER_H
|
||||
|
||||
#include "player.h"
|
||||
|
||||
// @bindclass
|
||||
class LocalPlayer : public Player
|
||||
{
|
||||
enum {
|
||||
PREWALK_TIMEOUT = 1000
|
||||
};
|
||||
|
||||
public:
|
||||
LocalPlayer();
|
||||
|
||||
void unlockWalk() { m_walkLockExpiration = 0; }
|
||||
void lockWalk(int millis = 250);
|
||||
void stopAutoWalkUpdate();
|
||||
void updateAutoWalkSteps(bool walkFailed = false);
|
||||
bool autoWalk(const Position& destination);
|
||||
bool canWalk(Otc::Direction direction);
|
||||
|
||||
void setStates(int states);
|
||||
void setSkill(Otc::Skill skill, int level, int levelPercent);
|
||||
void setBaseSkill(Otc::Skill skill, int baseLevel);
|
||||
void setHealth(double health, double maxHealth);
|
||||
void setFreeCapacity(double freeCapacity);
|
||||
void setTotalCapacity(double totalCapacity);
|
||||
void setExperience(double experience);
|
||||
void setLevel(double level, double levelPercent);
|
||||
void setMana(double mana, double maxMana);
|
||||
void setMagicLevel(double magicLevel, double magicLevelPercent);
|
||||
void setBaseMagicLevel(double baseMagicLevel);
|
||||
void setSoul(double soul);
|
||||
void setStamina(double stamina);
|
||||
void setKnown(bool known) { m_known = known; }
|
||||
void setPendingGame(bool pending) { m_pending = pending; }
|
||||
void setInventoryItem(Otc::InventorySlot inventory, const ItemPtr& item);
|
||||
void setVocation(int vocation);
|
||||
void setPremium(bool premium);
|
||||
void setBaseSpeed(double baseSpeed);
|
||||
void setRegenerationTime(double regenerationTime);
|
||||
void setOfflineTrainingTime(double offlineTrainingTime);
|
||||
void setSpells(const std::vector<int>& spells);
|
||||
|
||||
int getStates() { return m_states; }
|
||||
int getSkillLevel(Otc::Skill skill) { return m_skillsLevel[skill]; }
|
||||
int getSkillBaseLevel(Otc::Skill skill) { return m_skillsBaseLevel[skill]; }
|
||||
int getSkillLevelPercent(Otc::Skill skill) { return m_skillsLevelPercent[skill]; }
|
||||
int getVocation() { return m_vocation; }
|
||||
int getWalkPing() { return m_lastWalkPing; }
|
||||
double getHealth() { return m_health; }
|
||||
double getMaxHealth() { return m_maxHealth; }
|
||||
double getFreeCapacity() { return m_freeCapacity; }
|
||||
double getTotalCapacity() { return m_totalCapacity; }
|
||||
double getExperience() { return m_experience; }
|
||||
double getLevel() { return m_level; }
|
||||
double getLevelPercent() { return m_levelPercent; }
|
||||
double getMana() { return m_mana; }
|
||||
double getMaxMana() { return m_maxMana; }
|
||||
double getMagicLevel() { return m_magicLevel; }
|
||||
double getMagicLevelPercent() { return m_magicLevelPercent; }
|
||||
double getBaseMagicLevel() { return m_baseMagicLevel; }
|
||||
double getSoul() { return m_soul; }
|
||||
double getStamina() { return m_stamina; }
|
||||
double getBaseSpeed() { return m_baseSpeed; }
|
||||
double getRegenerationTime() { return m_regenerationTime; }
|
||||
double getOfflineTrainingTime() { return m_offlineTrainingTime; }
|
||||
std::vector<int> getSpells() { return m_spells; }
|
||||
ItemPtr getInventoryItem(Otc::InventorySlot inventory) { return m_inventoryItems[inventory]; }
|
||||
std::vector<Position> getAutoWalkSteps() { return m_autoWalkSteps; }
|
||||
|
||||
bool hasSight(const Position& pos);
|
||||
bool isKnown() { return m_known; }
|
||||
bool isPreWalking() { return m_preWalking; }
|
||||
bool isAutoWalking() { return m_autoWalking; }
|
||||
bool isPremium() { return m_premium; }
|
||||
bool isPendingGame() { return m_pending; }
|
||||
|
||||
LocalPlayerPtr asLocalPlayer() { return static_self_cast<LocalPlayer>(); }
|
||||
bool isLocalPlayer() { return true; }
|
||||
|
||||
virtual void onAppear();
|
||||
virtual void onPositionChange(const Position& newPos, const Position& oldPos);
|
||||
|
||||
protected:
|
||||
void walk(const Position& oldPos, const Position& newPos);
|
||||
void preWalk(Otc::Direction direction);
|
||||
void cancelWalk(Otc::Direction direction = Otc::InvalidDirection);
|
||||
void stopWalk();
|
||||
|
||||
friend class Game;
|
||||
|
||||
protected:
|
||||
void updateWalkOffset(int totalPixelsWalked);
|
||||
void updateWalk();
|
||||
void terminateWalk();
|
||||
|
||||
private:
|
||||
// walk related
|
||||
Timer m_walkPingTimer;
|
||||
Position m_lastPrewalkDestionation;
|
||||
Position m_lastAutoWalkDestination;
|
||||
ScheduledEventPtr m_autoWalkEndEvent;
|
||||
ticks_t m_walkLockExpiration;
|
||||
int m_lastWalkPing;
|
||||
stdext::boolean<false> m_preWalking;
|
||||
stdext::boolean<true> m_lastPrewalkDone;
|
||||
stdext::boolean<false> m_autoWalking;
|
||||
stdext::boolean<false> m_waitingWalkPong;
|
||||
|
||||
stdext::boolean<false> m_premium;
|
||||
stdext::boolean<false> m_known;
|
||||
stdext::boolean<false> m_pending;
|
||||
|
||||
ItemPtr m_inventoryItems[Otc::LastInventorySlot];
|
||||
Timer m_idleTimer;
|
||||
|
||||
std::array<int, Otc::LastSkill> m_skillsLevel;
|
||||
std::array<int, Otc::LastSkill> m_skillsBaseLevel;
|
||||
std::array<int, Otc::LastSkill> m_skillsLevelPercent;
|
||||
std::vector<int> m_spells;
|
||||
std::vector<Position> m_autoWalkSteps;
|
||||
|
||||
int m_states;
|
||||
int m_vocation;
|
||||
|
||||
double m_health;
|
||||
double m_maxHealth;
|
||||
double m_freeCapacity;
|
||||
double m_totalCapacity;
|
||||
double m_experience;
|
||||
double m_level;
|
||||
double m_levelPercent;
|
||||
double m_mana;
|
||||
double m_maxMana;
|
||||
double m_magicLevel;
|
||||
double m_magicLevelPercent;
|
||||
double m_baseMagicLevel;
|
||||
double m_soul;
|
||||
double m_stamina;
|
||||
double m_baseSpeed;
|
||||
double m_regenerationTime;
|
||||
double m_offlineTrainingTime;
|
||||
};
|
||||
|
||||
#endif
|
||||
561
src/client/luafunctions.cpp
Normal file
561
src/client/luafunctions.cpp
Normal file
@@ -0,0 +1,561 @@
|
||||
/*
|
||||
* Copyright (c) 2010-2013 OTClient <https://github.com/edubart/otclient>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "client.h"
|
||||
#include "luavaluecasts.h"
|
||||
#include "game.h"
|
||||
#include "tile.h"
|
||||
#include "houses.h"
|
||||
#include "towns.h"
|
||||
#include "container.h"
|
||||
#include "item.h"
|
||||
#include "effect.h"
|
||||
#include "missile.h"
|
||||
#include "statictext.h"
|
||||
#include "animatedtext.h"
|
||||
#include "creature.h"
|
||||
#include "player.h"
|
||||
#include "localplayer.h"
|
||||
#include "map.h"
|
||||
#include "thingtypemanager.h"
|
||||
#include "spritemanager.h"
|
||||
#include "shadermanager.h"
|
||||
#include "protocolgame.h"
|
||||
#include "uiitem.h"
|
||||
#include "uicreature.h"
|
||||
#include "uimap.h"
|
||||
#include "uiprogressrect.h"
|
||||
#include "outfit.h"
|
||||
|
||||
#include <framework/luaengine/luainterface.h>
|
||||
|
||||
void Client::registerLuaFunctions()
|
||||
{
|
||||
g_lua.registerSingletonClass("g_things");
|
||||
g_lua.bindSingletonFunction("g_things", "loadDat", &ThingTypeManager::loadDat, &g_things);
|
||||
g_lua.bindSingletonFunction("g_things", "loadOtb", &ThingTypeManager::loadOtb, &g_things);
|
||||
g_lua.bindSingletonFunction("g_things", "loadXml", &ThingTypeManager::loadXml, &g_things);
|
||||
g_lua.bindSingletonFunction("g_things", "isDatLoaded", &ThingTypeManager::isDatLoaded, &g_things);
|
||||
g_lua.bindSingletonFunction("g_things", "isOtbLoaded", &ThingTypeManager::isOtbLoaded, &g_things);
|
||||
g_lua.bindSingletonFunction("g_things", "getDatSignature", &ThingTypeManager::getDatSignature, &g_things);
|
||||
g_lua.bindSingletonFunction("g_things", "getDatSignature", &ThingTypeManager::getDatSignature, &g_things);
|
||||
g_lua.bindSingletonFunction("g_things", "getThingType", &ThingTypeManager::getThingType, &g_things);
|
||||
g_lua.bindSingletonFunction("g_things", "getItemType", &ThingTypeManager::getItemType, &g_things);
|
||||
g_lua.bindSingletonFunction("g_things", "getThingTypes", &ThingTypeManager::getThingTypes, &g_things);
|
||||
g_lua.bindSingletonFunction("g_things", "findItemTypeByClientId", &ThingTypeManager::findItemTypeByClientId, &g_things);
|
||||
g_lua.bindSingletonFunction("g_things", "findThingTypeByAttr", &ThingTypeManager::findThingTypeByAttr, &g_things);
|
||||
g_lua.bindSingletonFunction("g_things", "findItemTypeByCategory", &ThingTypeManager::findItemTypeByCategory, &g_things);
|
||||
|
||||
g_lua.registerSingletonClass("g_houses");
|
||||
g_lua.bindSingletonFunction("g_houses", "clear", &HouseManager::clear, &g_houses);
|
||||
g_lua.bindSingletonFunction("g_houses", "load", &HouseManager::load, &g_houses);
|
||||
g_lua.bindSingletonFunction("g_houses", "save", &HouseManager::save, &g_houses);
|
||||
g_lua.bindSingletonFunction("g_houses", "getHouse", &HouseManager::getHouse, &g_houses);
|
||||
g_lua.bindSingletonFunction("g_houses", "addHouse", &HouseManager::addHouse, &g_houses);
|
||||
g_lua.bindSingletonFunction("g_houses", "removeHouse", &HouseManager::removeHouse, &g_houses);
|
||||
g_lua.bindSingletonFunction("g_houses", "getHouseList", &HouseManager::getHouseList, &g_houses);
|
||||
|
||||
g_lua.registerSingletonClass("g_towns");
|
||||
g_lua.bindSingletonFunction("g_towns", "getTown", &TownManager::getTown, &g_towns);
|
||||
g_lua.bindSingletonFunction("g_towns", "addTown", &TownManager::addTown, &g_towns);
|
||||
g_lua.bindSingletonFunction("g_towns", "removeTown", &TownManager::removeTown, &g_towns);
|
||||
g_lua.bindSingletonFunction("g_towns", "getTowns", &TownManager::getTowns, &g_towns);
|
||||
|
||||
g_lua.registerSingletonClass("g_sprites");
|
||||
g_lua.bindSingletonFunction("g_sprites", "loadSpr", &SpriteManager::loadSpr, &g_sprites);
|
||||
g_lua.bindSingletonFunction("g_sprites", "unload", &SpriteManager::unload, &g_sprites);
|
||||
g_lua.bindSingletonFunction("g_sprites", "isLoaded", &SpriteManager::isLoaded, &g_sprites);
|
||||
g_lua.bindSingletonFunction("g_sprites", "getSprSignature", &SpriteManager::getSignature, &g_sprites);
|
||||
g_lua.bindSingletonFunction("g_sprites", "getSpritesCount", &SpriteManager::getSpritesCount, &g_sprites);
|
||||
|
||||
g_lua.registerSingletonClass("g_map");
|
||||
g_lua.bindSingletonFunction("g_map", "isLookPossible", &Map::isLookPossible, &g_map);
|
||||
g_lua.bindSingletonFunction("g_map", "isCovered", &Map::isCovered, &g_map);
|
||||
g_lua.bindSingletonFunction("g_map", "isCompletelyCovered", &Map::isCompletelyCovered, &g_map);
|
||||
g_lua.bindSingletonFunction("g_map", "addThing", &Map::addThing, &g_map);
|
||||
g_lua.bindSingletonFunction("g_map", "getThing", &Map::getThing, &g_map);
|
||||
g_lua.bindSingletonFunction("g_map", "removeThingByPos", &Map::removeThingByPos, &g_map);
|
||||
g_lua.bindSingletonFunction("g_map", "removeThing", &Map::removeThing, &g_map);
|
||||
g_lua.bindSingletonFunction("g_map", "clean", &Map::clean, &g_map);
|
||||
g_lua.bindSingletonFunction("g_map", "cleanTile", &Map::cleanTile, &g_map);
|
||||
g_lua.bindSingletonFunction("g_map", "cleanTexts", &Map::cleanTexts, &g_map);
|
||||
g_lua.bindSingletonFunction("g_map", "getTile", &Map::getTile, &g_map);
|
||||
g_lua.bindSingletonFunction("g_map", "setCentralPosition", &Map::setCentralPosition, &g_map);
|
||||
g_lua.bindSingletonFunction("g_map", "getCentralPosition", &Map::getCentralPosition, &g_map);
|
||||
g_lua.bindSingletonFunction("g_map", "getCreatureById", &Map::getCreatureById, &g_map);
|
||||
g_lua.bindSingletonFunction("g_map", "removeCreatureById", &Map::removeCreatureById, &g_map);
|
||||
g_lua.bindSingletonFunction("g_map", "getSpectators", &Map::getSpectators, &g_map);
|
||||
g_lua.bindSingletonFunction("g_map", "findPath", &Map::findPath, &g_map);
|
||||
g_lua.bindSingletonFunction("g_map", "loadOtbm", &Map::loadOtbm, &g_map);
|
||||
g_lua.bindSingletonFunction("g_map", "saveOtbm", &Map::saveOtbm, &g_map);
|
||||
g_lua.bindSingletonFunction("g_map", "loadOtcm", &Map::loadOtcm, &g_map);
|
||||
g_lua.bindSingletonFunction("g_map", "saveOtcm", &Map::saveOtcm, &g_map);
|
||||
g_lua.bindSingletonFunction("g_map", "getHouseFile", &Map::getHouseFile, &g_map);
|
||||
g_lua.bindSingletonFunction("g_map", "setHouseFile", &Map::setHouseFile, &g_map);
|
||||
g_lua.bindSingletonFunction("g_map", "getSpawnFile", &Map::getSpawnFile, &g_map);
|
||||
g_lua.bindSingletonFunction("g_map", "setSpawnFile", &Map::setSpawnFile, &g_map);
|
||||
g_lua.bindSingletonFunction("g_map", "createTile", &Map::createTile, &g_map);
|
||||
g_lua.bindSingletonFunction("g_map", "getSize", &Map::getSize, &g_map);;
|
||||
|
||||
g_lua.registerSingletonClass("g_creatures");
|
||||
g_lua.bindSingletonFunction("g_creatures", "getCreatures", &CreatureManager::getCreatures, &g_creatures);
|
||||
g_lua.bindSingletonFunction("g_creatures", "getCreatureByName", &CreatureManager::getCreatureByName, &g_creatures);
|
||||
g_lua.bindSingletonFunction("g_creatures", "getCreatureByLook", &CreatureManager::getCreatureByLook, &g_creatures);
|
||||
g_lua.bindSingletonFunction("g_creatures", "getSpawn", &CreatureManager::getSpawn, &g_creatures);
|
||||
g_lua.bindSingletonFunction("g_creatures", "addSpawn", &CreatureManager::addSpawn, &g_creatures);
|
||||
g_lua.bindSingletonFunction("g_creatures", "loadMonsters", &CreatureManager::loadMonsters, &g_creatures);
|
||||
g_lua.bindSingletonFunction("g_creatures", "loadNpcs", &CreatureManager::loadNpcs, &g_creatures);
|
||||
g_lua.bindSingletonFunction("g_creatures", "loadSingleCreature", &CreatureManager::loadSingleCreature, &g_creatures);
|
||||
g_lua.bindSingletonFunction("g_creatures", "loadSpawns", &CreatureManager::loadSpawns, &g_creatures);
|
||||
g_lua.bindSingletonFunction("g_creatures", "saveSpawns", &CreatureManager::saveSpawns, &g_creatures);
|
||||
g_lua.bindSingletonFunction("g_creatures", "isLoaded", &CreatureManager::isLoaded, &g_creatures);
|
||||
g_lua.bindSingletonFunction("g_creatures", "isSpawnLoaded", &CreatureManager::isSpawnLoaded, &g_creatures);
|
||||
g_lua.bindSingletonFunction("g_creatures", "clear", &CreatureManager::clear, &g_creatures);
|
||||
g_lua.bindSingletonFunction("g_creatures", "clearSpawns", &CreatureManager::clearSpawns, &g_creatures);
|
||||
|
||||
g_lua.registerSingletonClass("g_game");
|
||||
g_lua.bindSingletonFunction("g_game", "loginWorld", &Game::loginWorld, &g_game);
|
||||
g_lua.bindSingletonFunction("g_game", "cancelLogin", &Game::cancelLogin, &g_game);
|
||||
g_lua.bindSingletonFunction("g_game", "forceLogout", &Game::forceLogout, &g_game);
|
||||
g_lua.bindSingletonFunction("g_game", "safeLogout", &Game::safeLogout, &g_game);
|
||||
g_lua.bindSingletonFunction("g_game", "walk", &Game::walk, &g_game);
|
||||
g_lua.bindSingletonFunction("g_game", "autoWalk", &Game::autoWalk, &g_game);
|
||||
g_lua.bindSingletonFunction("g_game", "forceWalk", &Game::forceWalk, &g_game);
|
||||
g_lua.bindSingletonFunction("g_game", "turn", &Game::turn, &g_game);
|
||||
g_lua.bindSingletonFunction("g_game", "stop", &Game::stop, &g_game);
|
||||
g_lua.bindSingletonFunction("g_game", "look", &Game::look, &g_game);
|
||||
g_lua.bindSingletonFunction("g_game", "move", &Game::move, &g_game);
|
||||
g_lua.bindSingletonFunction("g_game", "moveToParentContainer", &Game::moveToParentContainer, &g_game);
|
||||
g_lua.bindSingletonFunction("g_game", "rotate", &Game::rotate, &g_game);
|
||||
g_lua.bindSingletonFunction("g_game", "use", &Game::use, &g_game);
|
||||
g_lua.bindSingletonFunction("g_game", "useWith", &Game::useWith, &g_game);
|
||||
g_lua.bindSingletonFunction("g_game", "useInventoryItem", &Game::useInventoryItem, &g_game);
|
||||
g_lua.bindSingletonFunction("g_game", "useInventoryItemWith", &Game::useInventoryItemWith, &g_game);
|
||||
g_lua.bindSingletonFunction("g_game", "open", &Game::open, &g_game);
|
||||
g_lua.bindSingletonFunction("g_game", "openParent", &Game::openParent, &g_game);
|
||||
g_lua.bindSingletonFunction("g_game", "close", &Game::close, &g_game);
|
||||
g_lua.bindSingletonFunction("g_game", "refreshContainer", &Game::refreshContainer, &g_game);
|
||||
g_lua.bindSingletonFunction("g_game", "attack", &Game::attack, &g_game);
|
||||
g_lua.bindSingletonFunction("g_game", "cancelAttack", &Game::cancelAttack, &g_game);
|
||||
g_lua.bindSingletonFunction("g_game", "follow", &Game::follow, &g_game);
|
||||
g_lua.bindSingletonFunction("g_game", "cancelFollow", &Game::cancelFollow, &g_game);
|
||||
g_lua.bindSingletonFunction("g_game", "cancelAttackAndFollow", &Game::cancelAttackAndFollow, &g_game);
|
||||
g_lua.bindSingletonFunction("g_game", "talk", &Game::talk, &g_game);
|
||||
g_lua.bindSingletonFunction("g_game", "talkChannel", &Game::talkChannel, &g_game);
|
||||
g_lua.bindSingletonFunction("g_game", "talkPrivate", &Game::talkPrivate, &g_game);
|
||||
g_lua.bindSingletonFunction("g_game", "openPrivateChannel", &Game::openPrivateChannel, &g_game);
|
||||
g_lua.bindSingletonFunction("g_game", "requestChannels", &Game::requestChannels, &g_game);
|
||||
g_lua.bindSingletonFunction("g_game", "joinChannel", &Game::joinChannel, &g_game);
|
||||
g_lua.bindSingletonFunction("g_game", "leaveChannel", &Game::leaveChannel, &g_game);
|
||||
g_lua.bindSingletonFunction("g_game", "closeNpcChannel", &Game::closeNpcChannel, &g_game);
|
||||
g_lua.bindSingletonFunction("g_game", "openOwnChannel", &Game::openOwnChannel, &g_game);
|
||||
g_lua.bindSingletonFunction("g_game", "inviteToOwnChannel", &Game::inviteToOwnChannel, &g_game);
|
||||
g_lua.bindSingletonFunction("g_game", "excludeFromOwnChannel", &Game::excludeFromOwnChannel, &g_game);
|
||||
g_lua.bindSingletonFunction("g_game", "partyInvite", &Game::partyInvite, &g_game);
|
||||
g_lua.bindSingletonFunction("g_game", "partyJoin", &Game::partyJoin, &g_game);
|
||||
g_lua.bindSingletonFunction("g_game", "partyRevokeInvitation", &Game::partyRevokeInvitation, &g_game);
|
||||
g_lua.bindSingletonFunction("g_game", "partyPassLeadership", &Game::partyPassLeadership, &g_game);
|
||||
g_lua.bindSingletonFunction("g_game", "partyLeave", &Game::partyLeave, &g_game);
|
||||
g_lua.bindSingletonFunction("g_game", "partyShareExperience", &Game::partyShareExperience, &g_game);
|
||||
g_lua.bindSingletonFunction("g_game", "requestOutfit", &Game::requestOutfit, &g_game);
|
||||
g_lua.bindSingletonFunction("g_game", "changeOutfit", &Game::changeOutfit, &g_game);
|
||||
g_lua.bindSingletonFunction("g_game", "addVip", &Game::addVip, &g_game);
|
||||
g_lua.bindSingletonFunction("g_game", "removeVip", &Game::removeVip, &g_game);
|
||||
g_lua.bindSingletonFunction("g_game", "setChaseMode", &Game::setChaseMode, &g_game);
|
||||
g_lua.bindSingletonFunction("g_game", "setFightMode", &Game::setFightMode, &g_game);
|
||||
g_lua.bindSingletonFunction("g_game", "setSafeFight", &Game::setSafeFight, &g_game);
|
||||
g_lua.bindSingletonFunction("g_game", "getChaseMode", &Game::getChaseMode, &g_game);
|
||||
g_lua.bindSingletonFunction("g_game", "getFightMode", &Game::getFightMode, &g_game);
|
||||
g_lua.bindSingletonFunction("g_game", "isSafeFight", &Game::isSafeFight, &g_game);
|
||||
g_lua.bindSingletonFunction("g_game", "inspectNpcTrade", &Game::inspectNpcTrade, &g_game);
|
||||
g_lua.bindSingletonFunction("g_game", "buyItem", &Game::buyItem, &g_game);
|
||||
g_lua.bindSingletonFunction("g_game", "sellItem", &Game::sellItem, &g_game);
|
||||
g_lua.bindSingletonFunction("g_game", "closeNpcTrade", &Game::closeNpcTrade, &g_game);
|
||||
g_lua.bindSingletonFunction("g_game", "requestTrade", &Game::requestTrade, &g_game);
|
||||
g_lua.bindSingletonFunction("g_game", "inspectTrade", &Game::inspectTrade, &g_game);
|
||||
g_lua.bindSingletonFunction("g_game", "acceptTrade", &Game::acceptTrade, &g_game);
|
||||
g_lua.bindSingletonFunction("g_game", "rejectTrade", &Game::rejectTrade, &g_game);
|
||||
g_lua.bindSingletonFunction("g_game", "reportBug", &Game::reportBug, &g_game);
|
||||
g_lua.bindSingletonFunction("g_game", "reportRuleViolation", &Game::reportRuleViolation, &g_game);
|
||||
g_lua.bindSingletonFunction("g_game", "debugReport", &Game::debugReport, &g_game);
|
||||
g_lua.bindSingletonFunction("g_game", "editText", &Game::editText, &g_game);
|
||||
g_lua.bindSingletonFunction("g_game", "editList", &Game::editList, &g_game);
|
||||
g_lua.bindSingletonFunction("g_game", "requestQuestLog", &Game::requestQuestLog, &g_game);
|
||||
g_lua.bindSingletonFunction("g_game", "requestQuestLine", &Game::requestQuestLine, &g_game);
|
||||
g_lua.bindSingletonFunction("g_game", "equipItem", &Game::equipItem, &g_game);
|
||||
g_lua.bindSingletonFunction("g_game", "mount", &Game::mount, &g_game);
|
||||
g_lua.bindSingletonFunction("g_game", "requestItemInfo", &Game::requestItemInfo, &g_game);
|
||||
g_lua.bindSingletonFunction("g_game", "ping", &Game::ping, &g_game);
|
||||
g_lua.bindSingletonFunction("g_game", "canPerformGameAction", &Game::canPerformGameAction, &g_game);
|
||||
g_lua.bindSingletonFunction("g_game", "canReportBugs", &Game::canReportBugs, &g_game);
|
||||
g_lua.bindSingletonFunction("g_game", "checkBotProtection", &Game::checkBotProtection, &g_game);
|
||||
g_lua.bindSingletonFunction("g_game", "isOnline", &Game::isOnline, &g_game);
|
||||
g_lua.bindSingletonFunction("g_game", "isDead", &Game::isDead, &g_game);
|
||||
g_lua.bindSingletonFunction("g_game", "isAttacking", &Game::isAttacking, &g_game);
|
||||
g_lua.bindSingletonFunction("g_game", "isFollowing", &Game::isFollowing, &g_game);
|
||||
g_lua.bindSingletonFunction("g_game", "getPing", &Game::getPing, &g_game);
|
||||
g_lua.bindSingletonFunction("g_game", "getContainer", &Game::getContainer, &g_game);
|
||||
g_lua.bindSingletonFunction("g_game", "getContainers", &Game::getContainers, &g_game);
|
||||
g_lua.bindSingletonFunction("g_game", "getVips", &Game::getVips, &g_game);
|
||||
g_lua.bindSingletonFunction("g_game", "getAttackingCreature", &Game::getAttackingCreature, &g_game);
|
||||
g_lua.bindSingletonFunction("g_game", "getFollowingCreature", &Game::getFollowingCreature, &g_game);
|
||||
g_lua.bindSingletonFunction("g_game", "getServerBeat", &Game::getServerBeat, &g_game);
|
||||
g_lua.bindSingletonFunction("g_game", "getLocalPlayer", &Game::getLocalPlayer, &g_game);
|
||||
g_lua.bindSingletonFunction("g_game", "getProtocolGame", &Game::getProtocolGame, &g_game);
|
||||
g_lua.bindSingletonFunction("g_game", "getProtocolVersion", &Game::getProtocolVersion, &g_game);
|
||||
g_lua.bindSingletonFunction("g_game", "setProtocolVersion", &Game::setProtocolVersion, &g_game);
|
||||
g_lua.bindSingletonFunction("g_game", "getClientVersion", &Game::getClientVersion, &g_game);
|
||||
g_lua.bindSingletonFunction("g_game", "setClientVersion", &Game::setClientVersion, &g_game);
|
||||
g_lua.bindSingletonFunction("g_game", "getCharacterName", &Game::getCharacterName, &g_game);
|
||||
g_lua.bindSingletonFunction("g_game", "getWorldName", &Game::getWorldName, &g_game);
|
||||
g_lua.bindSingletonFunction("g_game", "getGMActions", &Game::getGMActions, &g_game);
|
||||
g_lua.bindSingletonFunction("g_game", "getFeature", &Game::getFeature, &g_game);
|
||||
g_lua.bindSingletonFunction("g_game", "setFeature", &Game::setFeature, &g_game);
|
||||
g_lua.bindSingletonFunction("g_game", "enableFeature", &Game::enableFeature, &g_game);
|
||||
g_lua.bindSingletonFunction("g_game", "answerModalDialog", &Game::answerModalDialog, &g_game);
|
||||
|
||||
g_lua.registerSingletonClass("g_shaders");
|
||||
g_lua.bindSingletonFunction("g_shaders", "createShader", &ShaderManager::createShader, &g_shaders);
|
||||
g_lua.bindSingletonFunction("g_shaders", "createFragmentShader", &ShaderManager::createFragmentShader, &g_shaders);
|
||||
g_lua.bindSingletonFunction("g_shaders", "createFragmentShaderFromCode", &ShaderManager::createFragmentShaderFromCode, &g_shaders);
|
||||
g_lua.bindSingletonFunction("g_shaders", "createItemShader", &ShaderManager::createItemShader, &g_shaders);
|
||||
g_lua.bindSingletonFunction("g_shaders", "createMapShader", &ShaderManager::createMapShader, &g_shaders);
|
||||
g_lua.bindSingletonFunction("g_shaders", "getDefaultItemShader", &ShaderManager::getDefaultItemShader, &g_shaders);
|
||||
g_lua.bindSingletonFunction("g_shaders", "getDefaultMapShader", &ShaderManager::getDefaultMapShader, &g_shaders);
|
||||
g_lua.bindSingletonFunction("g_shaders", "getShader", &ShaderManager::getShader, &g_shaders);
|
||||
|
||||
g_lua.bindGlobalFunction("getOufitColor", Outfit::getColor);
|
||||
|
||||
g_lua.registerClass<ProtocolGame, Protocol>();
|
||||
g_lua.bindClassStaticFunction<ProtocolGame>("create", []{ return ProtocolGamePtr(new ProtocolGame); });
|
||||
g_lua.bindClassMemberFunction<ProtocolGame>("login", &ProtocolGame::login);
|
||||
g_lua.bindClassMemberFunction<ProtocolGame>("sendExtendedOpcode", &ProtocolGame::sendExtendedOpcode);
|
||||
g_lua.bindClassMemberFunction<ProtocolGame>("addPosition", &ProtocolGame::addPosition);
|
||||
g_lua.bindClassMemberFunction<ProtocolGame>("setMapDescription", &ProtocolGame::setMapDescription);
|
||||
g_lua.bindClassMemberFunction<ProtocolGame>("setFloorDescription", &ProtocolGame::setFloorDescription);
|
||||
g_lua.bindClassMemberFunction<ProtocolGame>("setTileDescription", &ProtocolGame::setTileDescription);
|
||||
g_lua.bindClassMemberFunction<ProtocolGame>("getOutfit", &ProtocolGame::getOutfit);
|
||||
g_lua.bindClassMemberFunction<ProtocolGame>("getThing", &ProtocolGame::getThing);
|
||||
g_lua.bindClassMemberFunction<ProtocolGame>("getCreature", &ProtocolGame::getCreature);
|
||||
g_lua.bindClassMemberFunction<ProtocolGame>("getItem", &ProtocolGame::getItem);
|
||||
g_lua.bindClassMemberFunction<ProtocolGame>("getPosition", &ProtocolGame::getPosition);
|
||||
|
||||
g_lua.registerClass<Container>();
|
||||
g_lua.bindClassMemberFunction<Container>("getItem", &Container::getItem);
|
||||
g_lua.bindClassMemberFunction<Container>("getItems", &Container::getItems);
|
||||
g_lua.bindClassMemberFunction<Container>("getItemsCount", &Container::getItemsCount);
|
||||
g_lua.bindClassMemberFunction<Container>("getSlotPosition", &Container::getSlotPosition);
|
||||
g_lua.bindClassMemberFunction<Container>("getName", &Container::getName);
|
||||
g_lua.bindClassMemberFunction<Container>("getId", &Container::getId);
|
||||
g_lua.bindClassMemberFunction<Container>("getCapacity", &Container::getCapacity);
|
||||
g_lua.bindClassMemberFunction<Container>("getContainerItem", &Container::getContainerItem);
|
||||
g_lua.bindClassMemberFunction<Container>("hasParent", &Container::hasParent);
|
||||
g_lua.bindClassMemberFunction<Container>("isClosed", &Container::isClosed);
|
||||
|
||||
g_lua.registerClass<Thing>();
|
||||
g_lua.bindClassMemberFunction<Thing>("setId", &Thing::setId);
|
||||
g_lua.bindClassMemberFunction<Thing>("setPosition", &Thing::setPosition);
|
||||
g_lua.bindClassMemberFunction<Thing>("getId", &Thing::getId);
|
||||
g_lua.bindClassMemberFunction<Thing>("getPosition", &Thing::getPosition);
|
||||
g_lua.bindClassMemberFunction<Thing>("getStackPriority", &Thing::getStackPriority);
|
||||
g_lua.bindClassMemberFunction<Thing>("getAnimationPhases", &Thing::getAnimationPhases);
|
||||
g_lua.bindClassMemberFunction<Thing>("isItem", &Thing::isItem);
|
||||
g_lua.bindClassMemberFunction<Thing>("isMonster", &Thing::isMonster);
|
||||
g_lua.bindClassMemberFunction<Thing>("isNpc", &Thing::isNpc);
|
||||
g_lua.bindClassMemberFunction<Thing>("isCreature", &Thing::isCreature);
|
||||
g_lua.bindClassMemberFunction<Thing>("isEffect", &Thing::isEffect);
|
||||
g_lua.bindClassMemberFunction<Thing>("isMissile", &Thing::isMissile);
|
||||
g_lua.bindClassMemberFunction<Thing>("isPlayer", &Thing::isPlayer);
|
||||
g_lua.bindClassMemberFunction<Thing>("isLocalPlayer", &Thing::isLocalPlayer);
|
||||
g_lua.bindClassMemberFunction<Thing>("isAnimatedText", &Thing::isAnimatedText);
|
||||
g_lua.bindClassMemberFunction<Thing>("isStaticText", &Thing::isStaticText);
|
||||
g_lua.bindClassMemberFunction<Thing>("isGround", &Thing::isGround);
|
||||
g_lua.bindClassMemberFunction<Thing>("isGroundBorder", &Thing::isGroundBorder);
|
||||
g_lua.bindClassMemberFunction<Thing>("isOnBottom", &Thing::isOnBottom);
|
||||
g_lua.bindClassMemberFunction<Thing>("isOnTop", &Thing::isOnTop);
|
||||
g_lua.bindClassMemberFunction<Thing>("isContainer", &Thing::isContainer);
|
||||
g_lua.bindClassMemberFunction<Thing>("isForceUse", &Thing::isForceUse);
|
||||
g_lua.bindClassMemberFunction<Thing>("isMultiUse", &Thing::isMultiUse);
|
||||
g_lua.bindClassMemberFunction<Thing>("isRotateable", &Thing::isRotateable);
|
||||
g_lua.bindClassMemberFunction<Thing>("isNotMoveable", &Thing::isNotMoveable);
|
||||
g_lua.bindClassMemberFunction<Thing>("isPickupable", &Thing::isPickupable);
|
||||
g_lua.bindClassMemberFunction<Thing>("isIgnoreLook", &Thing::isIgnoreLook);
|
||||
g_lua.bindClassMemberFunction<Thing>("isStackable", &Thing::isStackable);
|
||||
g_lua.bindClassMemberFunction<Thing>("isHookSouth", &Thing::isHookSouth);
|
||||
g_lua.bindClassMemberFunction<Thing>("isTranslucent", &Thing::isTranslucent);
|
||||
g_lua.bindClassMemberFunction<Thing>("isFullGround", &Thing::isFullGround);
|
||||
g_lua.bindClassMemberFunction<Thing>("isMarketable", &Thing::isMarketable);
|
||||
g_lua.bindClassMemberFunction<Thing>("getParentContainer", &Thing::getParentContainer);
|
||||
g_lua.bindClassMemberFunction<Thing>("getMarketData", &Thing::getMarketData);
|
||||
|
||||
g_lua.registerClass<House>();
|
||||
g_lua.bindClassStaticFunction<House>("create", []{ return HousePtr(new House); });
|
||||
g_lua.bindClassMemberFunction<House>("setId", &House::setId);
|
||||
g_lua.bindClassMemberFunction<House>("setName", &House::setName);
|
||||
g_lua.bindClassMemberFunction<House>("getName", &House::getName);
|
||||
g_lua.bindClassMemberFunction<House>("setTownId", &House::setTownId);
|
||||
g_lua.bindClassMemberFunction<House>("getTownId", &House::getTownId);
|
||||
g_lua.bindClassMemberFunction<House>("setTile", &House::setTile);
|
||||
g_lua.bindClassMemberFunction<House>("getTile", &House::getTile);
|
||||
g_lua.bindClassMemberFunction<House>("setEntry", &House::setEntry);
|
||||
g_lua.bindClassMemberFunction<House>("getEntry", &House::getEntry);
|
||||
g_lua.bindClassMemberFunction<House>("setSize", &House::setSize);
|
||||
g_lua.bindClassMemberFunction<House>("getSize", &House::getSize);
|
||||
g_lua.bindClassMemberFunction<House>("setRent", &House::setRent);
|
||||
g_lua.bindClassMemberFunction<House>("getRent", &House::getRent);
|
||||
|
||||
g_lua.registerClass<Spawn>();
|
||||
g_lua.bindClassStaticFunction<Spawn>("create", []{ return SpawnPtr(new Spawn); });
|
||||
g_lua.bindClassMemberFunction<Spawn>("setRadius", &Spawn::setRadius);
|
||||
g_lua.bindClassMemberFunction<Spawn>("getRadius", &Spawn::getRadius);
|
||||
g_lua.bindClassMemberFunction<Spawn>("setCenterPos", &Spawn::setCenterPos);
|
||||
g_lua.bindClassMemberFunction<Spawn>("getCenterPos", &Spawn::getCenterPos);
|
||||
g_lua.bindClassMemberFunction<Spawn>("addCreature", &Spawn::addCreature);
|
||||
g_lua.bindClassMemberFunction<Spawn>("removeCreature", &Spawn::removeCreature);
|
||||
|
||||
g_lua.registerClass<Town>();
|
||||
g_lua.bindClassStaticFunction<Town>("create", []{ return TownPtr(new Town); });
|
||||
g_lua.bindClassMemberFunction<Town>("setId", &Town::setId);
|
||||
g_lua.bindClassMemberFunction<Town>("setName", &Town::setName);
|
||||
g_lua.bindClassMemberFunction<Town>("setPos", &Town::setPos);
|
||||
g_lua.bindClassMemberFunction<Town>("setTemplePos", &Town::setPos); // alternative method
|
||||
g_lua.bindClassMemberFunction<Town>("getId", &Town::getId);
|
||||
g_lua.bindClassMemberFunction<Town>("getName", &Town::getName);
|
||||
g_lua.bindClassMemberFunction<Town>("getPos", &Town::getPos);
|
||||
g_lua.bindClassMemberFunction<Town>("getTemplePos", &Town::getPos); // alternative method
|
||||
|
||||
g_lua.registerClass<CreatureType>();
|
||||
g_lua.bindClassStaticFunction<CreatureType>("create", []{ return CreatureTypePtr(new CreatureType); });
|
||||
g_lua.bindClassMemberFunction<CreatureType>("setName", &CreatureType::setName);
|
||||
g_lua.bindClassMemberFunction<CreatureType>("setOutfit", &CreatureType::setOutfit);
|
||||
g_lua.bindClassMemberFunction<CreatureType>("setSpawnTime", &CreatureType::setSpawnTime);
|
||||
g_lua.bindClassMemberFunction<CreatureType>("getName", &CreatureType::getName);
|
||||
g_lua.bindClassMemberFunction<CreatureType>("getOutfit", &CreatureType::getOutfit);
|
||||
g_lua.bindClassMemberFunction<CreatureType>("getSpawnTime", &CreatureType::getSpawnTime);
|
||||
g_lua.bindClassMemberFunction<CreatureType>("cast", &CreatureType::cast);
|
||||
|
||||
g_lua.registerClass<Creature, Thing>();
|
||||
g_lua.bindClassStaticFunction<Creature>("create", []{ return CreaturePtr(new Creature); });
|
||||
g_lua.bindClassMemberFunction<Creature>("getId", &Creature::getId);
|
||||
g_lua.bindClassMemberFunction<Creature>("getName", &Creature::getName);
|
||||
g_lua.bindClassMemberFunction<Creature>("getHealthPercent", &Creature::getHealthPercent);
|
||||
g_lua.bindClassMemberFunction<Creature>("getSpeed", &Creature::getSpeed);
|
||||
g_lua.bindClassMemberFunction<Creature>("getSkull", &Creature::getSkull);
|
||||
g_lua.bindClassMemberFunction<Creature>("getShield", &Creature::getShield);
|
||||
g_lua.bindClassMemberFunction<Creature>("getEmblem", &Creature::getEmblem);
|
||||
g_lua.bindClassMemberFunction<Creature>("setOutfit", &Creature::setOutfit);
|
||||
g_lua.bindClassMemberFunction<Creature>("getOutfit", &Creature::getOutfit);
|
||||
g_lua.bindClassMemberFunction<Creature>("getDirection", &Creature::getDirection);
|
||||
g_lua.bindClassMemberFunction<Creature>("getStepDuration", &Creature::getStepDuration);
|
||||
g_lua.bindClassMemberFunction<Creature>("getStepProgress", &Creature::getStepProgress);
|
||||
g_lua.bindClassMemberFunction<Creature>("getWalkTicksElapsed", &Creature::getWalkTicksElapsed);
|
||||
g_lua.bindClassMemberFunction<Creature>("getStepTicksLeft", &Creature::getStepTicksLeft);
|
||||
g_lua.bindClassMemberFunction<Creature>("setDirection", &Creature::setDirection);
|
||||
g_lua.bindClassMemberFunction<Creature>("setSkullTexture", &Creature::setSkullTexture);
|
||||
g_lua.bindClassMemberFunction<Creature>("setShieldTexture", &Creature::setShieldTexture);
|
||||
g_lua.bindClassMemberFunction<Creature>("setEmblemTexture", &Creature::setEmblemTexture);
|
||||
g_lua.bindClassMemberFunction<Creature>("showStaticSquare", &Creature::showStaticSquare);
|
||||
g_lua.bindClassMemberFunction<Creature>("hideStaticSquare", &Creature::hideStaticSquare);
|
||||
g_lua.bindClassMemberFunction<Creature>("isWalking", &Creature::isWalking);
|
||||
g_lua.bindClassMemberFunction<Creature>("isInvisible", &Creature::isInvisible);
|
||||
g_lua.bindClassMemberFunction<Creature>("canBeSeen", &Creature::canBeSeen);
|
||||
|
||||
g_lua.registerClass<ItemType>();
|
||||
g_lua.bindClassMemberFunction<ItemType>("getServerId", &ItemType::getServerId);
|
||||
g_lua.bindClassMemberFunction<ItemType>("getClientId", &ItemType::getClientId);
|
||||
|
||||
g_lua.registerClass<ThingType>();
|
||||
g_lua.bindClassMemberFunction<ThingType>("getId", &ThingType::getId);
|
||||
g_lua.bindClassMemberFunction<ThingType>("getMarketData", &ThingType::getMarketData);
|
||||
g_lua.bindClassMemberFunction<ThingType>("getClothSlot", &ThingType::getClothSlot);
|
||||
g_lua.bindClassMemberFunction<ThingType>("getCategory", &ThingType::getCategory);
|
||||
|
||||
g_lua.registerClass<Item, Thing>();
|
||||
g_lua.bindClassStaticFunction<Item>("create", &Item::create);
|
||||
g_lua.bindClassStaticFunction<Item>("createOtb", &Item::createFromOtb);
|
||||
g_lua.bindClassMemberFunction<Item>("clone", &Item::clone);
|
||||
g_lua.bindClassMemberFunction<Item>("setCount", &Item::setCount);
|
||||
g_lua.bindClassMemberFunction<Item>("getCount", &Item::getCount);
|
||||
g_lua.bindClassMemberFunction<Item>("getId", &Item::getId);
|
||||
g_lua.bindClassMemberFunction<Item>("isStackable", &Item::isStackable);
|
||||
g_lua.bindClassMemberFunction<Item>("isMarketable", &Item::isMarketable);
|
||||
g_lua.bindClassMemberFunction<Item>("getMarketData", &Item::getMarketData);
|
||||
g_lua.bindClassMemberFunction<Item>("getClothSlot", &Item::getClothSlot);
|
||||
|
||||
g_lua.registerClass<Effect, Thing>();
|
||||
g_lua.registerClass<Missile, Thing>();
|
||||
|
||||
g_lua.registerClass<StaticText, Thing>();
|
||||
g_lua.bindClassStaticFunction<StaticText>("create", []{ return StaticTextPtr(new StaticText); });
|
||||
g_lua.bindClassMemberFunction<StaticText>("addMessage", &StaticText::addMessage);
|
||||
|
||||
g_lua.registerClass<AnimatedText, Thing>();
|
||||
|
||||
g_lua.registerClass<Player, Creature>();
|
||||
g_lua.registerClass<Npc, Creature>();
|
||||
g_lua.registerClass<Monster, Creature>();
|
||||
|
||||
g_lua.registerClass<LocalPlayer, Player>();
|
||||
g_lua.bindClassMemberFunction<LocalPlayer>("unlockWalk", &LocalPlayer::unlockWalk);
|
||||
g_lua.bindClassMemberFunction<LocalPlayer>("lockWalk", &LocalPlayer::lockWalk);
|
||||
g_lua.bindClassMemberFunction<LocalPlayer>("canWalk", &LocalPlayer::canWalk);
|
||||
g_lua.bindClassMemberFunction<LocalPlayer>("setStates", &LocalPlayer::setStates);
|
||||
g_lua.bindClassMemberFunction<LocalPlayer>("setSkill", &LocalPlayer::setSkill);
|
||||
g_lua.bindClassMemberFunction<LocalPlayer>("setHealth", &LocalPlayer::setHealth);
|
||||
g_lua.bindClassMemberFunction<LocalPlayer>("setTotalCapacity", &LocalPlayer::setTotalCapacity);
|
||||
g_lua.bindClassMemberFunction<LocalPlayer>("setFreeCapacity", &LocalPlayer::setFreeCapacity);
|
||||
g_lua.bindClassMemberFunction<LocalPlayer>("setExperience", &LocalPlayer::setExperience);
|
||||
g_lua.bindClassMemberFunction<LocalPlayer>("setLevel", &LocalPlayer::setLevel);
|
||||
g_lua.bindClassMemberFunction<LocalPlayer>("setMana", &LocalPlayer::setMana);
|
||||
g_lua.bindClassMemberFunction<LocalPlayer>("setMagicLevel", &LocalPlayer::setMagicLevel);
|
||||
g_lua.bindClassMemberFunction<LocalPlayer>("setSoul", &LocalPlayer::setSoul);
|
||||
g_lua.bindClassMemberFunction<LocalPlayer>("setStamina", &LocalPlayer::setStamina);
|
||||
g_lua.bindClassMemberFunction<LocalPlayer>("setKnown", &LocalPlayer::setKnown);
|
||||
g_lua.bindClassMemberFunction<LocalPlayer>("setInventoryItem", &LocalPlayer::setInventoryItem);
|
||||
g_lua.bindClassMemberFunction<LocalPlayer>("getStates", &LocalPlayer::getStates);
|
||||
g_lua.bindClassMemberFunction<LocalPlayer>("getSkillLevel", &LocalPlayer::getSkillLevel);
|
||||
g_lua.bindClassMemberFunction<LocalPlayer>("getSkillBaseLevel", &LocalPlayer::getSkillBaseLevel);
|
||||
g_lua.bindClassMemberFunction<LocalPlayer>("getSkillLevelPercent", &LocalPlayer::getSkillLevelPercent);
|
||||
g_lua.bindClassMemberFunction<LocalPlayer>("getHealth", &LocalPlayer::getHealth);
|
||||
g_lua.bindClassMemberFunction<LocalPlayer>("getMaxHealth", &LocalPlayer::getMaxHealth);
|
||||
g_lua.bindClassMemberFunction<LocalPlayer>("getFreeCapacity", &LocalPlayer::getFreeCapacity);
|
||||
g_lua.bindClassMemberFunction<LocalPlayer>("getExperience", &LocalPlayer::getExperience);
|
||||
g_lua.bindClassMemberFunction<LocalPlayer>("getLevel", &LocalPlayer::getLevel);
|
||||
g_lua.bindClassMemberFunction<LocalPlayer>("getLevelPercent", &LocalPlayer::getLevelPercent);
|
||||
g_lua.bindClassMemberFunction<LocalPlayer>("getMana", &LocalPlayer::getMana);
|
||||
g_lua.bindClassMemberFunction<LocalPlayer>("getMaxMana", &LocalPlayer::getMaxMana);
|
||||
g_lua.bindClassMemberFunction<LocalPlayer>("getMagicLevel", &LocalPlayer::getMagicLevel);
|
||||
g_lua.bindClassMemberFunction<LocalPlayer>("getMagicLevelPercent", &LocalPlayer::getMagicLevelPercent);
|
||||
g_lua.bindClassMemberFunction<LocalPlayer>("getSoul", &LocalPlayer::getSoul);
|
||||
g_lua.bindClassMemberFunction<LocalPlayer>("getStamina", &LocalPlayer::getStamina);
|
||||
g_lua.bindClassMemberFunction<LocalPlayer>("getOfflineTrainingTime", &LocalPlayer::getOfflineTrainingTime);
|
||||
g_lua.bindClassMemberFunction<LocalPlayer>("getRegenerationTime", &LocalPlayer::getRegenerationTime);
|
||||
g_lua.bindClassMemberFunction<LocalPlayer>("getBaseSpeed", &LocalPlayer::getBaseSpeed);
|
||||
g_lua.bindClassMemberFunction<LocalPlayer>("getBaseMagicLevel", &LocalPlayer::getBaseMagicLevel);
|
||||
g_lua.bindClassMemberFunction<LocalPlayer>("getTotalCapacity", &LocalPlayer::getTotalCapacity);
|
||||
g_lua.bindClassMemberFunction<LocalPlayer>("getInventoryItem", &LocalPlayer::getInventoryItem);
|
||||
g_lua.bindClassMemberFunction<LocalPlayer>("getVocation", &LocalPlayer::getVocation);
|
||||
g_lua.bindClassMemberFunction<LocalPlayer>("getWalkPing", &LocalPlayer::getWalkPing);
|
||||
g_lua.bindClassMemberFunction<LocalPlayer>("isPremium", &LocalPlayer::isPremium);
|
||||
g_lua.bindClassMemberFunction<LocalPlayer>("isKnown", &LocalPlayer::isKnown);
|
||||
g_lua.bindClassMemberFunction<LocalPlayer>("isPreWalking", &LocalPlayer::isPreWalking);
|
||||
g_lua.bindClassMemberFunction<LocalPlayer>("hasSight", &LocalPlayer::hasSight);
|
||||
g_lua.bindClassMemberFunction<LocalPlayer>("isAutoWalking", &LocalPlayer::isAutoWalking);
|
||||
g_lua.bindClassMemberFunction<LocalPlayer>("stopAutoWalkUpdate", &LocalPlayer::stopAutoWalkUpdate);
|
||||
g_lua.bindClassMemberFunction<LocalPlayer>("updateAutoWalkSteps", &LocalPlayer::updateAutoWalkSteps);
|
||||
g_lua.bindClassMemberFunction<LocalPlayer>("autoWalk", &LocalPlayer::autoWalk);
|
||||
g_lua.bindClassMemberFunction<LocalPlayer>("getAutoWalkSteps", &LocalPlayer::getAutoWalkSteps);
|
||||
|
||||
g_lua.registerClass<Tile>();
|
||||
g_lua.bindClassMemberFunction<Tile>("clean", &Tile::clean);
|
||||
g_lua.bindClassMemberFunction<Tile>("addThing", &Tile::addThing);
|
||||
g_lua.bindClassMemberFunction<Tile>("getThing", &Tile::getThing);
|
||||
g_lua.bindClassMemberFunction<Tile>("getThingStackpos", &Tile::getThingStackpos);
|
||||
g_lua.bindClassMemberFunction<Tile>("getThingCount", &Tile::getThingCount);
|
||||
g_lua.bindClassMemberFunction<Tile>("getTopThing", &Tile::getTopThing);
|
||||
g_lua.bindClassMemberFunction<Tile>("removeThing", &Tile::removeThing);
|
||||
g_lua.bindClassMemberFunction<Tile>("getTopLookThing", &Tile::getTopLookThing);
|
||||
g_lua.bindClassMemberFunction<Tile>("getTopUseThing", &Tile::getTopUseThing);
|
||||
g_lua.bindClassMemberFunction<Tile>("getTopCreature", &Tile::getTopCreature);
|
||||
g_lua.bindClassMemberFunction<Tile>("getTopMoveThing", &Tile::getTopMoveThing);
|
||||
g_lua.bindClassMemberFunction<Tile>("getTopMultiUseThing", &Tile::getTopMultiUseThing);
|
||||
g_lua.bindClassMemberFunction<Tile>("getPosition", &Tile::getPosition);
|
||||
g_lua.bindClassMemberFunction<Tile>("getDrawElevation", &Tile::getDrawElevation);
|
||||
g_lua.bindClassMemberFunction<Tile>("getCreatures", &Tile::getCreatures);
|
||||
g_lua.bindClassMemberFunction<Tile>("getGround", &Tile::getGround);
|
||||
g_lua.bindClassMemberFunction<Tile>("isWalkable", &Tile::isWalkable);
|
||||
g_lua.bindClassMemberFunction<Tile>("isFullGround", &Tile::isFullGround);
|
||||
g_lua.bindClassMemberFunction<Tile>("isFullyOpaque", &Tile::isFullyOpaque);
|
||||
g_lua.bindClassMemberFunction<Tile>("isLookPossible", &Tile::isLookPossible);
|
||||
g_lua.bindClassMemberFunction<Tile>("hasCreature", &Tile::hasCreature);
|
||||
g_lua.bindClassMemberFunction<Tile>("isEmpty", &Tile::isEmpty);
|
||||
g_lua.bindClassMemberFunction<Tile>("isClickable", &Tile::isClickable);
|
||||
|
||||
g_lua.registerClass<UIItem, UIWidget>();
|
||||
g_lua.bindClassStaticFunction<UIItem>("create", []{ return UIItemPtr(new UIItem); });
|
||||
g_lua.bindClassMemberFunction<UIItem>("setItemId", &UIItem::setItemId);
|
||||
g_lua.bindClassMemberFunction<UIItem>("setItemCount", &UIItem::setItemCount);
|
||||
g_lua.bindClassMemberFunction<UIItem>("setItemSubType", &UIItem::setItemSubType);
|
||||
g_lua.bindClassMemberFunction<UIItem>("setItem", &UIItem::setItem);
|
||||
g_lua.bindClassMemberFunction<UIItem>("setVirtual", &UIItem::setVirtual);
|
||||
g_lua.bindClassMemberFunction<UIItem>("clearItem", &UIItem::clearItem);
|
||||
g_lua.bindClassMemberFunction<UIItem>("getItemId", &UIItem::getItemId);
|
||||
g_lua.bindClassMemberFunction<UIItem>("getItemCount", &UIItem::getItemCount);
|
||||
g_lua.bindClassMemberFunction<UIItem>("getItemSubType", &UIItem::getItemSubType);
|
||||
g_lua.bindClassMemberFunction<UIItem>("getItem", &UIItem::getItem);
|
||||
g_lua.bindClassMemberFunction<UIItem>("isVirtual", &UIItem::isVirtual);
|
||||
|
||||
g_lua.registerClass<UICreature, UIWidget>();
|
||||
g_lua.bindClassStaticFunction<UICreature>("create", []{ return UICreaturePtr(new UICreature); } );
|
||||
g_lua.bindClassMemberFunction<UICreature>("setCreature", &UICreature::setCreature);
|
||||
g_lua.bindClassMemberFunction<UICreature>("setOutfit", &UICreature::setOutfit);
|
||||
g_lua.bindClassMemberFunction<UICreature>("setFixedCreatureSize", &UICreature::setFixedCreatureSize);
|
||||
g_lua.bindClassMemberFunction<UICreature>("getCreature", &UICreature::getCreature);
|
||||
g_lua.bindClassMemberFunction<UICreature>("isFixedCreatureSize", &UICreature::isFixedCreatureSize);
|
||||
|
||||
g_lua.registerClass<UIMap, UIWidget>();
|
||||
g_lua.bindClassStaticFunction<UIMap>("create", []{ return UIMapPtr(new UIMap); });
|
||||
g_lua.bindClassMemberFunction<UIMap>("drawSelf", &UIMap::drawSelf);
|
||||
g_lua.bindClassMemberFunction<UIMap>("setZoom", &UIMap::setZoom);
|
||||
g_lua.bindClassMemberFunction<UIMap>("zoomIn", &UIMap::zoomIn);
|
||||
g_lua.bindClassMemberFunction<UIMap>("zoomOut", &UIMap::zoomOut);
|
||||
g_lua.bindClassMemberFunction<UIMap>("followCreature", &UIMap::followCreature);
|
||||
g_lua.bindClassMemberFunction<UIMap>("setCameraPosition", &UIMap::setCameraPosition);
|
||||
g_lua.bindClassMemberFunction<UIMap>("setMaxZoomIn", &UIMap::setMaxZoomIn);
|
||||
g_lua.bindClassMemberFunction<UIMap>("setMaxZoomOut", &UIMap::setMaxZoomOut);
|
||||
g_lua.bindClassMemberFunction<UIMap>("setMultifloor", &UIMap::setMultifloor);
|
||||
g_lua.bindClassMemberFunction<UIMap>("setVisibleDimension", &UIMap::setVisibleDimension);
|
||||
g_lua.bindClassMemberFunction<UIMap>("setViewMode", &UIMap::setViewMode);
|
||||
g_lua.bindClassMemberFunction<UIMap>("setAutoViewMode", &UIMap::setAutoViewMode);
|
||||
g_lua.bindClassMemberFunction<UIMap>("setDrawFlags", &UIMap::setDrawFlags);
|
||||
g_lua.bindClassMemberFunction<UIMap>("setDrawTexts", &UIMap::setDrawTexts);
|
||||
g_lua.bindClassMemberFunction<UIMap>("setDrawMinimapColors", &UIMap::setDrawMinimapColors);
|
||||
g_lua.bindClassMemberFunction<UIMap>("setDrawLights", &UIMap::setDrawLights);
|
||||
g_lua.bindClassMemberFunction<UIMap>("setAnimated", &UIMap::setAnimated);
|
||||
g_lua.bindClassMemberFunction<UIMap>("setKeepAspectRatio", &UIMap::setKeepAspectRatio);
|
||||
g_lua.bindClassMemberFunction<UIMap>("setMapShader", &UIMap::setMapShader);
|
||||
g_lua.bindClassMemberFunction<UIMap>("setMinimumAmbientLight", &UIMap::setMinimumAmbientLight);
|
||||
g_lua.bindClassMemberFunction<UIMap>("isMultifloor", &UIMap::isMultifloor);
|
||||
g_lua.bindClassMemberFunction<UIMap>("isAutoViewModeEnabled", &UIMap::isAutoViewModeEnabled);
|
||||
g_lua.bindClassMemberFunction<UIMap>("isDrawingTexts", &UIMap::isDrawingTexts);
|
||||
g_lua.bindClassMemberFunction<UIMap>("isDrawingMinimapColors", &UIMap::isDrawingMinimapColors);
|
||||
g_lua.bindClassMemberFunction<UIMap>("isDrawingLights", &UIMap::isDrawingLights);
|
||||
g_lua.bindClassMemberFunction<UIMap>("isAnimating", &UIMap::isAnimating);
|
||||
g_lua.bindClassMemberFunction<UIMap>("isKeepAspectRatioEnabled", &UIMap::isKeepAspectRatioEnabled);
|
||||
g_lua.bindClassMemberFunction<UIMap>("getVisibleDimension", &UIMap::getVisibleDimension);
|
||||
g_lua.bindClassMemberFunction<UIMap>("getViewMode", &UIMap::getViewMode);
|
||||
g_lua.bindClassMemberFunction<UIMap>("getFollowingCreature", &UIMap::getFollowingCreature);
|
||||
g_lua.bindClassMemberFunction<UIMap>("getDrawFlags", &UIMap::getDrawFlags);
|
||||
g_lua.bindClassMemberFunction<UIMap>("getCameraPosition", &UIMap::getCameraPosition);
|
||||
g_lua.bindClassMemberFunction<UIMap>("getPosition", &UIMap::getPosition);
|
||||
g_lua.bindClassMemberFunction<UIMap>("getTile", &UIMap::getTile);
|
||||
g_lua.bindClassMemberFunction<UIMap>("getMaxZoomIn", &UIMap::getMaxZoomIn);
|
||||
g_lua.bindClassMemberFunction<UIMap>("getMaxZoomOut", &UIMap::getMaxZoomOut);
|
||||
g_lua.bindClassMemberFunction<UIMap>("getZoom", &UIMap::getZoom);
|
||||
g_lua.bindClassMemberFunction<UIMap>("getMapShader", &UIMap::getMapShader);
|
||||
g_lua.bindClassMemberFunction<UIMap>("getMinimumAmbientLight", &UIMap::getMinimumAmbientLight);
|
||||
|
||||
g_lua.registerClass<UIProgressRect, UIWidget>();
|
||||
g_lua.bindClassStaticFunction<UIProgressRect>("create", []{ return UIProgressRectPtr(new UIProgressRect); } );
|
||||
g_lua.bindClassMemberFunction<UIProgressRect>("setPercent", &UIProgressRect::setPercent);
|
||||
g_lua.bindClassMemberFunction<UIProgressRect>("getPercent", &UIProgressRect::getPercent);
|
||||
}
|
||||
141
src/client/luavaluecasts.cpp
Normal file
141
src/client/luavaluecasts.cpp
Normal file
@@ -0,0 +1,141 @@
|
||||
/*
|
||||
* Copyright (c) 2010-2013 OTClient <https://github.com/edubart/otclient>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "luavaluecasts.h"
|
||||
#include <framework/luaengine/luainterface.h>
|
||||
|
||||
int push_luavalue(const Outfit& outfit)
|
||||
{
|
||||
g_lua.newTable();
|
||||
g_lua.pushInteger(outfit.getId());
|
||||
g_lua.setField("type");
|
||||
g_lua.pushInteger(outfit.getAuxId());
|
||||
g_lua.setField("auxType");
|
||||
g_lua.pushInteger(outfit.getAddons());
|
||||
g_lua.setField("addons");
|
||||
g_lua.pushInteger(outfit.getHead());
|
||||
g_lua.setField("head");
|
||||
g_lua.pushInteger(outfit.getBody());
|
||||
g_lua.setField("body");
|
||||
g_lua.pushInteger(outfit.getLegs());
|
||||
g_lua.setField("legs");
|
||||
g_lua.pushInteger(outfit.getFeet());
|
||||
g_lua.setField("feet");
|
||||
if(g_game.getFeature(Otc::GamePlayerMounts)) {
|
||||
g_lua.pushInteger(outfit.getMount());
|
||||
g_lua.setField("mount");
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool luavalue_cast(int index, Outfit& outfit)
|
||||
{
|
||||
if(g_lua.isTable(index)) {
|
||||
g_lua.getField("type", index);
|
||||
outfit.setId(g_lua.popInteger());
|
||||
g_lua.getField("auxType", index);
|
||||
outfit.setAuxId(g_lua.popInteger());
|
||||
g_lua.getField("addons", index);
|
||||
outfit.setAddons(g_lua.popInteger());
|
||||
g_lua.getField("head", index);
|
||||
outfit.setHead(g_lua.popInteger());
|
||||
g_lua.getField("body", index);
|
||||
outfit.setBody(g_lua.popInteger());
|
||||
g_lua.getField("legs", index);
|
||||
outfit.setLegs(g_lua.popInteger());
|
||||
g_lua.getField("feet", index);
|
||||
outfit.setFeet(g_lua.popInteger());
|
||||
if(g_game.getFeature(Otc::GamePlayerMounts)) {
|
||||
g_lua.getField("mount", index);
|
||||
outfit.setMount(g_lua.popInteger());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int push_luavalue(const Position& pos)
|
||||
{
|
||||
if(pos.isValid()) {
|
||||
g_lua.newTable();
|
||||
g_lua.pushInteger(pos.x);
|
||||
g_lua.setField("x");
|
||||
g_lua.pushInteger(pos.y);
|
||||
g_lua.setField("y");
|
||||
g_lua.pushInteger(pos.z);
|
||||
g_lua.setField("z");
|
||||
} else
|
||||
g_lua.pushNil();
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool luavalue_cast(int index, Position& pos)
|
||||
{
|
||||
if(g_lua.isTable(index)) {
|
||||
g_lua.getField("x", index);
|
||||
pos.x = g_lua.popInteger();
|
||||
g_lua.getField("y", index);
|
||||
pos.y = g_lua.popInteger();
|
||||
g_lua.getField("z", index);
|
||||
pos.z = g_lua.popInteger();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int push_luavalue(const MarketData& data)
|
||||
{
|
||||
g_lua.newTable();
|
||||
g_lua.pushInteger(data.category);
|
||||
g_lua.setField("category");
|
||||
g_lua.pushString(data.name);
|
||||
g_lua.setField("name");
|
||||
g_lua.pushInteger(data.requiredLevel);
|
||||
g_lua.setField("requiredLevel");
|
||||
g_lua.pushInteger(data.restrictVocation);
|
||||
g_lua.setField("restrictVocation");
|
||||
g_lua.pushInteger(data.showAs);
|
||||
g_lua.setField("showAs");
|
||||
g_lua.pushInteger(data.tradeAs);
|
||||
g_lua.setField("tradeAs");
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool luavalue_cast(int index, MarketData& data)
|
||||
{
|
||||
if(g_lua.isTable(index)) {
|
||||
g_lua.getField("category", index);
|
||||
data.category = g_lua.popInteger();
|
||||
g_lua.getField("name", index);
|
||||
data.name = g_lua.popString();
|
||||
g_lua.getField("requiredLevel", index);
|
||||
data.requiredLevel = g_lua.popInteger();
|
||||
g_lua.getField("restrictVocation", index);
|
||||
data.restrictVocation = g_lua.popInteger();
|
||||
g_lua.getField("showAs", index);
|
||||
data.showAs = g_lua.popInteger();
|
||||
g_lua.getField("tradeAs", index);
|
||||
data.tradeAs = g_lua.popInteger();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
43
src/client/luavaluecasts.h
Normal file
43
src/client/luavaluecasts.h
Normal file
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright (c) 2010-2013 OTClient <https://github.com/edubart/otclient>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef OTCLIENT_LUAVALUECASTS_H
|
||||
#define OTCLIENT_LUAVALUECASTS_H
|
||||
|
||||
#include "global.h"
|
||||
#include <framework/luaengine/declarations.h>
|
||||
#include "game.h"
|
||||
#include "outfit.h"
|
||||
|
||||
// outfit
|
||||
int push_luavalue(const Outfit& outfit);
|
||||
bool luavalue_cast(int index, Outfit& outfit);
|
||||
|
||||
// position
|
||||
int push_luavalue(const Position& pos);
|
||||
bool luavalue_cast(int index, Position& pos);
|
||||
|
||||
// market
|
||||
int push_luavalue(const MarketData& data);
|
||||
bool luavalue_cast(int index, MarketData& data);
|
||||
|
||||
#endif
|
||||
584
src/client/map.cpp
Normal file
584
src/client/map.cpp
Normal file
@@ -0,0 +1,584 @@
|
||||
/*
|
||||
* Copyright (c) 2010-2013 OTClient <https://github.com/edubart/otclient>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "map.h"
|
||||
#include "game.h"
|
||||
#include "localplayer.h"
|
||||
#include "tile.h"
|
||||
#include "item.h"
|
||||
#include "missile.h"
|
||||
#include "statictext.h"
|
||||
#include "mapview.h"
|
||||
|
||||
#include <framework/core/eventdispatcher.h>
|
||||
#include <framework/core/application.h>
|
||||
|
||||
Map g_map;
|
||||
TilePtr Map::m_nulltile;
|
||||
|
||||
void Map::terminate()
|
||||
{
|
||||
clean();
|
||||
}
|
||||
|
||||
void Map::addMapView(const MapViewPtr& mapView)
|
||||
{
|
||||
m_mapViews.push_back(mapView);
|
||||
}
|
||||
|
||||
void Map::removeMapView(const MapViewPtr& mapView)
|
||||
{
|
||||
auto it = std::find(m_mapViews.begin(), m_mapViews.end(), mapView);
|
||||
if(it != m_mapViews.end())
|
||||
m_mapViews.erase(it);
|
||||
}
|
||||
|
||||
void Map::notificateTileUpdateToMapViews(const Position& pos)
|
||||
{
|
||||
for(const MapViewPtr& mapView : m_mapViews)
|
||||
mapView->onTileUpdate(pos);
|
||||
}
|
||||
|
||||
void Map::clean()
|
||||
{
|
||||
cleanDynamicThings();
|
||||
|
||||
for(int i=0;i<=Otc::MAX_Z;++i)
|
||||
m_tileBlocks[i].clear();
|
||||
|
||||
m_waypoints.clear();
|
||||
|
||||
g_towns.clear();
|
||||
g_houses.clear();
|
||||
g_creatures.clearSpawns();
|
||||
m_tilesRect = Rect(65534, 65534, 0, 0);
|
||||
}
|
||||
|
||||
void Map::cleanDynamicThings()
|
||||
{
|
||||
for(const auto& pair : m_knownCreatures) {
|
||||
const CreaturePtr& creature = pair.second;
|
||||
removeThing(creature);
|
||||
}
|
||||
m_knownCreatures.clear();
|
||||
|
||||
for(int i=0;i<=Otc::MAX_Z;++i)
|
||||
m_floorMissiles[i].clear();
|
||||
|
||||
cleanTexts();
|
||||
}
|
||||
|
||||
void Map::cleanTexts()
|
||||
{
|
||||
m_animatedTexts.clear();
|
||||
m_staticTexts.clear();
|
||||
}
|
||||
|
||||
void Map::addThing(const ThingPtr& thing, const Position& pos, int stackPos)
|
||||
{
|
||||
if(!thing)
|
||||
return;
|
||||
|
||||
if(thing->isItem() || thing->isCreature() || thing->isEffect()) {
|
||||
const TilePtr& tile = getOrCreateTile(pos);
|
||||
tile->addThing(thing, stackPos);
|
||||
} else {
|
||||
if(thing->isMissile()) {
|
||||
m_floorMissiles[pos.z].push_back(thing->static_self_cast<Missile>());
|
||||
thing->onAppear();
|
||||
} else if(thing->isAnimatedText()) {
|
||||
AnimatedTextPtr animatedText = thing->static_self_cast<AnimatedText>();
|
||||
m_animatedTexts.push_back(animatedText);
|
||||
} else if(thing->isStaticText()) {
|
||||
StaticTextPtr staticText = thing->static_self_cast<StaticText>();
|
||||
bool mustAdd = true;
|
||||
for(auto other : m_staticTexts) {
|
||||
// try to combine messages
|
||||
if(other->getPosition() == pos && other->addMessage(staticText->getName(), staticText->getMessageMode(), staticText->getFirstMessage())) {
|
||||
mustAdd = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(mustAdd) {
|
||||
m_staticTexts.push_back(staticText);
|
||||
staticText->onAppear();
|
||||
}
|
||||
}
|
||||
|
||||
thing->setPosition(pos);
|
||||
thing->onAppear();
|
||||
}
|
||||
|
||||
notificateTileUpdateToMapViews(pos);
|
||||
}
|
||||
|
||||
ThingPtr Map::getThing(const Position& pos, int stackPos)
|
||||
{
|
||||
if(TilePtr tile = getTile(pos))
|
||||
return tile->getThing(stackPos);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool Map::removeThing(const ThingPtr& thing)
|
||||
{
|
||||
if(!thing)
|
||||
return false;
|
||||
|
||||
notificateTileUpdateToMapViews(thing->getPosition());
|
||||
|
||||
if(thing->isMissile()) {
|
||||
MissilePtr missile = thing->static_self_cast<Missile>();
|
||||
int z = missile->getPosition().z;
|
||||
auto it = std::find(m_floorMissiles[z].begin(), m_floorMissiles[z].end(), missile);
|
||||
if(it != m_floorMissiles[z].end()) {
|
||||
m_floorMissiles[z].erase(it);
|
||||
return true;
|
||||
}
|
||||
} else if(thing->isAnimatedText()) {
|
||||
AnimatedTextPtr animatedText = thing->static_self_cast<AnimatedText>();
|
||||
auto it = std::find(m_animatedTexts.begin(), m_animatedTexts.end(), animatedText);
|
||||
if(it != m_animatedTexts.end()) {
|
||||
m_animatedTexts.erase(it);
|
||||
return true;
|
||||
}
|
||||
} else if(thing->isStaticText()) {
|
||||
StaticTextPtr staticText = thing->static_self_cast<StaticText>();
|
||||
auto it = std::find(m_staticTexts.begin(), m_staticTexts.end(), staticText);
|
||||
if(it != m_staticTexts.end()) {
|
||||
m_staticTexts.erase(it);
|
||||
return true;
|
||||
}
|
||||
} else if(const TilePtr& tile = thing->getTile())
|
||||
return tile->removeThing(thing);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Map::removeThingByPos(const Position& pos, int stackPos)
|
||||
{
|
||||
if(TilePtr tile = getTile(pos))
|
||||
return removeThing(tile->getThing(stackPos));
|
||||
return false;
|
||||
}
|
||||
|
||||
const TilePtr& Map::createTile(const Position& pos)
|
||||
{
|
||||
if(!pos.isMapPosition())
|
||||
return m_nulltile;
|
||||
if(pos.x < m_tilesRect.left())
|
||||
m_tilesRect.setLeft(pos.x);
|
||||
if(pos.y < m_tilesRect.top())
|
||||
m_tilesRect.setTop(pos.y);
|
||||
if(pos.x > m_tilesRect.right())
|
||||
m_tilesRect.setRight(pos.x);
|
||||
if(pos.y > m_tilesRect.bottom())
|
||||
m_tilesRect.setBottom(pos.y);
|
||||
TileBlock& block = m_tileBlocks[pos.z][getBlockIndex(pos)];
|
||||
return block.create(pos);
|
||||
}
|
||||
|
||||
template <typename... Items>
|
||||
const TilePtr& Map::createTileEx(const Position& pos, const Items&... items)
|
||||
{
|
||||
if(!pos.isValid())
|
||||
return m_nulltile;
|
||||
const TilePtr& tile = getOrCreateTile(pos);
|
||||
auto vec = {items...};
|
||||
for(auto it : vec)
|
||||
addThing(it, pos);
|
||||
|
||||
return tile;
|
||||
}
|
||||
|
||||
const TilePtr& Map::getOrCreateTile(const Position& pos)
|
||||
{
|
||||
if(!pos.isMapPosition())
|
||||
return m_nulltile;
|
||||
if(pos.x < m_tilesRect.left())
|
||||
m_tilesRect.setLeft(pos.x);
|
||||
if(pos.y < m_tilesRect.top())
|
||||
m_tilesRect.setTop(pos.y);
|
||||
if(pos.x > m_tilesRect.right())
|
||||
m_tilesRect.setRight(pos.x);
|
||||
if(pos.y > m_tilesRect.bottom())
|
||||
m_tilesRect.setBottom(pos.y);
|
||||
TileBlock& block = m_tileBlocks[pos.z][getBlockIndex(pos)];
|
||||
return block.getOrCreate(pos);
|
||||
}
|
||||
|
||||
const TilePtr& Map::getTile(const Position& pos)
|
||||
{
|
||||
if(!pos.isMapPosition())
|
||||
return m_nulltile;
|
||||
auto it = m_tileBlocks[pos.z].find(getBlockIndex(pos));
|
||||
if(it != m_tileBlocks[pos.z].end())
|
||||
return it->second.get(pos);
|
||||
return m_nulltile;
|
||||
}
|
||||
|
||||
void Map::cleanTile(const Position& pos)
|
||||
{
|
||||
if(!pos.isMapPosition())
|
||||
return;
|
||||
auto it = m_tileBlocks[pos.z].find(getBlockIndex(pos));
|
||||
if(it != m_tileBlocks[pos.z].end()) {
|
||||
TileBlock& block = it->second;
|
||||
if(const TilePtr& tile = block.get(pos)) {
|
||||
tile->clean();
|
||||
if(tile->canErase())
|
||||
block.remove(pos);
|
||||
|
||||
notificateTileUpdateToMapViews(pos);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Map::addCreature(const CreaturePtr& creature)
|
||||
{
|
||||
m_knownCreatures[creature->getId()] = creature;
|
||||
}
|
||||
|
||||
CreaturePtr Map::getCreatureById(uint32 id)
|
||||
{
|
||||
auto it = m_knownCreatures.find(id);
|
||||
if(it == m_knownCreatures.end())
|
||||
return nullptr;
|
||||
return it->second;
|
||||
}
|
||||
|
||||
void Map::removeCreatureById(uint32 id)
|
||||
{
|
||||
if(id == 0)
|
||||
return;
|
||||
|
||||
auto it = m_knownCreatures.find(id);
|
||||
if(it != m_knownCreatures.end())
|
||||
m_knownCreatures.erase(it);
|
||||
}
|
||||
|
||||
void Map::setCentralPosition(const Position& centralPosition)
|
||||
{
|
||||
m_centralPosition = centralPosition;
|
||||
|
||||
// remove creatures from tiles that we are not aware anymore
|
||||
for(const auto& pair : m_knownCreatures) {
|
||||
const CreaturePtr& creature = pair.second;
|
||||
if(!isAwareOfPosition(creature->getPosition()))
|
||||
removeThing(creature);
|
||||
}
|
||||
|
||||
// this fixes local player position when the local player is removed from the map,
|
||||
// the local player is removed from the map when there are too many creatures on his tile,
|
||||
// so there is no enough stackpos to the server send him
|
||||
g_dispatcher.addEvent([this] {
|
||||
LocalPlayerPtr localPlayer = g_game.getLocalPlayer();
|
||||
if(!localPlayer || localPlayer->getPosition() == m_centralPosition)
|
||||
return;
|
||||
TilePtr tile = localPlayer->getTile();
|
||||
if(tile && tile->hasThing(localPlayer))
|
||||
return;
|
||||
|
||||
Position oldPos = localPlayer->getPosition();
|
||||
Position pos = m_centralPosition;
|
||||
if(oldPos != pos) {
|
||||
if(!localPlayer->isRemoved())
|
||||
localPlayer->onDisappear();
|
||||
localPlayer->setPosition(pos);
|
||||
localPlayer->onAppear();
|
||||
g_logger.debug("forced player position update");
|
||||
}
|
||||
});
|
||||
|
||||
for(const MapViewPtr& mapView : m_mapViews)
|
||||
mapView->onMapCenterChange(centralPosition);
|
||||
}
|
||||
|
||||
std::vector<CreaturePtr> Map::getSpectators(const Position& centerPos, bool multiFloor)
|
||||
{
|
||||
return getSpectatorsInRange(centerPos, multiFloor, (Otc::VISIBLE_X_TILES - 1)/2, (Otc::VISIBLE_Y_TILES - 1)/2);
|
||||
}
|
||||
|
||||
std::vector<CreaturePtr> Map::getSpectatorsInRange(const Position& centerPos, bool multiFloor, int xRange, int yRange)
|
||||
{
|
||||
return getSpectatorsInRangeEx(centerPos, multiFloor, xRange, xRange, yRange, yRange);
|
||||
}
|
||||
|
||||
std::vector<CreaturePtr> Map::getSpectatorsInRangeEx(const Position& centerPos, bool multiFloor, int minXRange, int maxXRange, int minYRange, int maxYRange)
|
||||
{
|
||||
int minZRange = 0;
|
||||
int maxZRange = 0;
|
||||
std::vector<CreaturePtr> creatures;
|
||||
|
||||
if(multiFloor) {
|
||||
minZRange = 0;
|
||||
maxZRange = Otc::MAX_Z;
|
||||
}
|
||||
|
||||
//TODO: optimize
|
||||
//TODO: get creatures from other floors corretly
|
||||
//TODO: delivery creatures in distance order
|
||||
|
||||
for(int iz=-minZRange; iz<=maxZRange; ++iz) {
|
||||
for(int iy=-minYRange; iy<=maxYRange; ++iy) {
|
||||
for(int ix=-minXRange; ix<=maxXRange; ++ix) {
|
||||
TilePtr tile = getTile(centerPos.translated(ix,iy,iz));
|
||||
if(!tile)
|
||||
continue;
|
||||
|
||||
auto tileCreatures = tile->getCreatures();
|
||||
creatures.insert(creatures.end(), tileCreatures.rbegin(), tileCreatures.rend());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return creatures;
|
||||
}
|
||||
|
||||
bool Map::isLookPossible(const Position& pos)
|
||||
{
|
||||
TilePtr tile = getTile(pos);
|
||||
return tile && tile->isLookPossible();
|
||||
}
|
||||
|
||||
bool Map::isCovered(const Position& pos, int firstFloor)
|
||||
{
|
||||
// check for tiles on top of the postion
|
||||
Position tilePos = pos;
|
||||
while(tilePos.coveredUp() && tilePos.z >= firstFloor) {
|
||||
TilePtr tile = getTile(tilePos);
|
||||
// the below tile is covered when the above tile has a full ground
|
||||
if(tile && tile->isFullGround())
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Map::isCompletelyCovered(const Position& pos, int firstFloor)
|
||||
{
|
||||
const TilePtr& checkTile = getTile(pos);
|
||||
Position tilePos = pos;
|
||||
while(tilePos.coveredUp() && tilePos.z >= firstFloor) {
|
||||
bool covered = true;
|
||||
bool done = false;
|
||||
// check in 2x2 range tiles that has no transparent pixels
|
||||
for(int x=0;x<2 && !done;++x) {
|
||||
for(int y=0;y<2 && !done;++y) {
|
||||
const TilePtr& tile = getTile(tilePos.translated(-x, -y));
|
||||
if(!tile || !tile->isFullyOpaque()) {
|
||||
covered = false;
|
||||
done = true;
|
||||
} else if(x==0 && y==0 && (!checkTile || checkTile->isSingleDimension())) {
|
||||
done = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(covered)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Map::isAwareOfPosition(const Position& pos)
|
||||
{
|
||||
if(pos.z < getFirstAwareFloor() || pos.z > getLastAwareFloor())
|
||||
return false;
|
||||
|
||||
Position groundedPos = pos;
|
||||
while(groundedPos.z != m_centralPosition.z) {
|
||||
if(groundedPos.z > m_centralPosition.z)
|
||||
groundedPos.coveredUp();
|
||||
else
|
||||
groundedPos.coveredDown();
|
||||
}
|
||||
return m_centralPosition.isInRange(groundedPos, Otc::AWARE_X_LEFT_TILES,
|
||||
Otc::AWARE_X_RIGHT_TILES,
|
||||
Otc::AWARE_Y_TOP_TILES,
|
||||
Otc::AWARE_Y_BOTTOM_TILES);
|
||||
}
|
||||
|
||||
int Map::getFirstAwareFloor()
|
||||
{
|
||||
if(m_centralPosition.z > Otc::SEA_FLOOR)
|
||||
return m_centralPosition.z-Otc::AWARE_UNDEGROUND_FLOOR_RANGE;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Map::getLastAwareFloor()
|
||||
{
|
||||
if(m_centralPosition.z > Otc::SEA_FLOOR)
|
||||
return std::min(m_centralPosition.z+Otc::AWARE_UNDEGROUND_FLOOR_RANGE, (int)Otc::MAX_Z);
|
||||
else
|
||||
return Otc::SEA_FLOOR;
|
||||
}
|
||||
|
||||
std::tuple<std::vector<Otc::Direction>, Otc::PathFindResult> Map::findPath(const Position& startPos, const Position& goalPos, int maxSteps, int flags)
|
||||
{
|
||||
// pathfinding using A* search algorithm
|
||||
// as described in http://en.wikipedia.org/wiki/A*_search_algorithm
|
||||
|
||||
struct Node {
|
||||
Node(const Position& pos) : cost(0), totalCost(0), steps(0), pos(pos), prev(nullptr), dir(Otc::InvalidDirection), evaluated(false) { }
|
||||
bool operator<(const Node& other) const { return totalCost < other.totalCost; }
|
||||
float cost;
|
||||
float totalCost;
|
||||
int steps;
|
||||
Position pos;
|
||||
Node *prev;
|
||||
Otc::Direction dir;
|
||||
bool evaluated;
|
||||
};
|
||||
|
||||
struct LessNode : std::binary_function<Node*, Node*, bool> {
|
||||
bool operator()(Node* a, Node* b) const {
|
||||
return b->totalCost < a->totalCost;
|
||||
}
|
||||
};
|
||||
|
||||
std::tuple<std::vector<Otc::Direction>, Otc::PathFindResult> ret;
|
||||
std::vector<Otc::Direction>& dirs = std::get<0>(ret);
|
||||
Otc::PathFindResult& result = std::get<1>(ret);
|
||||
|
||||
result = Otc::PathFindResultNoWay;
|
||||
|
||||
if(startPos == goalPos) {
|
||||
result = Otc::PathFindResultSamePosition;
|
||||
return ret;
|
||||
}
|
||||
|
||||
if(startPos.z != goalPos.z) {
|
||||
result = Otc::PathFindResultImpossible;
|
||||
return ret;
|
||||
}
|
||||
|
||||
if(startPos.distance(goalPos) > maxSteps) {
|
||||
result = Otc::PathFindResultTooFar;
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::unordered_map<Position, Node*, PositionHasher> nodes;
|
||||
std::priority_queue<Node*, std::vector<Node*>, LessNode> searchList;
|
||||
|
||||
Node *currentNode = new Node(startPos);
|
||||
currentNode->pos = startPos;
|
||||
nodes[startPos] = currentNode;
|
||||
Node *foundNode = nullptr;
|
||||
while(currentNode) {
|
||||
// too far
|
||||
if(currentNode->steps >= maxSteps) {
|
||||
result = Otc::PathFindResultTooFar;
|
||||
break;
|
||||
}
|
||||
|
||||
// path found
|
||||
if(currentNode->pos == goalPos && (!foundNode || currentNode->cost < foundNode->cost))
|
||||
foundNode = currentNode;
|
||||
|
||||
// cost too high
|
||||
if(foundNode && currentNode->totalCost >= foundNode->cost)
|
||||
break;
|
||||
|
||||
for(int i=-1;i<=1;++i) {
|
||||
for(int j=-1;j<=1;++j) {
|
||||
if(i == 0 && j == 0)
|
||||
continue;
|
||||
|
||||
Position neighborPos = currentNode->pos.translated(i, j);
|
||||
const TilePtr& tile = getTile(neighborPos);
|
||||
|
||||
float walkFactor = 0;
|
||||
if(neighborPos != goalPos) {
|
||||
/*
|
||||
Known Issue with Otc::PathFindAllowNullTiles flag:
|
||||
If you are above ground floor this will attempt to path over null
|
||||
tiles, need to rework this for "fly servers" and blank map click,
|
||||
but it is breaking normal path finding.
|
||||
*/
|
||||
if(!(flags & Otc::PathFindAllowNullTiles) && !tile)
|
||||
walkFactor = 1.0f;
|
||||
if(tile) {
|
||||
if(!(flags & Otc::PathFindAllowCreatures) && tile->hasCreature())
|
||||
continue;
|
||||
if(!(flags & Otc::PathFindAllowNonPathable) && !tile->isPathable())
|
||||
continue;
|
||||
if(!(flags & Otc::PathFindAllowNonWalkable) && !tile->isWalkable())
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
Otc::Direction walkDir = currentNode->pos.getDirectionFromPosition(neighborPos);
|
||||
if(walkDir >= Otc::NorthEast)
|
||||
walkFactor += 3.0f;
|
||||
else
|
||||
walkFactor += 1.0f;
|
||||
|
||||
int groundSpeed = tile ? tile->getGroundSpeed() : 100;
|
||||
float cost = currentNode->cost + (groundSpeed * walkFactor) / 100.0f;
|
||||
|
||||
Node *neighborNode;
|
||||
if(nodes.find(neighborPos) == nodes.end()) {
|
||||
neighborNode = new Node(neighborPos);
|
||||
nodes[neighborPos] = neighborNode;
|
||||
} else {
|
||||
neighborNode = nodes[neighborPos];
|
||||
if(neighborNode->cost < cost)
|
||||
continue;
|
||||
}
|
||||
|
||||
neighborNode->prev = currentNode;
|
||||
neighborNode->cost = cost;
|
||||
neighborNode->steps = currentNode->steps + 1;
|
||||
neighborNode->totalCost = neighborNode->cost + neighborPos.distance(goalPos);
|
||||
neighborNode->dir = walkDir;
|
||||
neighborNode->evaluated = false;
|
||||
searchList.push(neighborNode);
|
||||
}
|
||||
}
|
||||
|
||||
currentNode->evaluated = true;
|
||||
currentNode = nullptr;
|
||||
while(searchList.size() > 0 && !currentNode) {
|
||||
Node *node = searchList.top();
|
||||
searchList.pop();
|
||||
|
||||
if(!node->evaluated)
|
||||
currentNode = node;
|
||||
}
|
||||
}
|
||||
|
||||
if(foundNode) {
|
||||
currentNode = foundNode;
|
||||
while(currentNode) {
|
||||
dirs.push_back(currentNode->dir);
|
||||
currentNode = currentNode->prev;
|
||||
}
|
||||
dirs.pop_back();
|
||||
std::reverse(dirs.begin(), dirs.end());
|
||||
result = Otc::PathFindResultOk;
|
||||
}
|
||||
|
||||
for(auto it : nodes)
|
||||
delete it.second;
|
||||
|
||||
return ret;
|
||||
}
|
||||
216
src/client/map.h
Normal file
216
src/client/map.h
Normal file
@@ -0,0 +1,216 @@
|
||||
/*
|
||||
* Copyright (c) 2010-2013 OTClient <https://github.com/edubart/otclient>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef MAP_H
|
||||
#define MAP_H
|
||||
|
||||
#include "creature.h"
|
||||
#include "houses.h"
|
||||
#include "towns.h"
|
||||
#include "creatures.h"
|
||||
#include "animatedtext.h"
|
||||
#include "statictext.h"
|
||||
#include "tile.h"
|
||||
|
||||
#include <framework/core/clock.h>
|
||||
|
||||
enum OTBM_ItemAttr
|
||||
{
|
||||
OTBM_ATTR_DESCRIPTION = 1,
|
||||
OTBM_ATTR_EXT_FILE = 2,
|
||||
OTBM_ATTR_TILE_FLAGS = 3,
|
||||
OTBM_ATTR_ACTION_ID = 4,
|
||||
OTBM_ATTR_UNIQUE_ID = 5,
|
||||
OTBM_ATTR_TEXT = 6,
|
||||
OTBM_ATTR_DESC = 7,
|
||||
OTBM_ATTR_TELE_DEST = 8,
|
||||
OTBM_ATTR_ITEM = 9,
|
||||
OTBM_ATTR_DEPOT_ID = 10,
|
||||
OTBM_ATTR_SPAWN_FILE = 11,
|
||||
OTBM_ATTR_RUNE_CHARGES = 12,
|
||||
OTBM_ATTR_HOUSE_FILE = 13,
|
||||
OTBM_ATTR_HOUSEDOORID = 14,
|
||||
OTBM_ATTR_COUNT = 15,
|
||||
OTBM_ATTR_DURATION = 16,
|
||||
OTBM_ATTR_DECAYING_STATE = 17,
|
||||
OTBM_ATTR_WRITTENDATE = 18,
|
||||
OTBM_ATTR_WRITTENBY = 19,
|
||||
OTBM_ATTR_SLEEPERGUID = 20,
|
||||
OTBM_ATTR_SLEEPSTART = 21,
|
||||
OTBM_ATTR_CHARGES = 22,
|
||||
OTBM_ATTR_CONTAINER_ITEMS = 23,
|
||||
OTBM_ATTR_ATTRIBUTE_MAP = 128,
|
||||
/// just random numbers, they're not actually used by the binary reader...
|
||||
OTBM_ATTR_WIDTH = 129,
|
||||
OTBM_ATTR_HEIGHT = 130
|
||||
};
|
||||
|
||||
enum OTBM_NodeTypes_t
|
||||
{
|
||||
OTBM_ROOTV2 = 1,
|
||||
OTBM_MAP_DATA = 2,
|
||||
OTBM_ITEM_DEF = 3,
|
||||
OTBM_TILE_AREA = 4,
|
||||
OTBM_TILE = 5,
|
||||
OTBM_ITEM = 6,
|
||||
OTBM_TILE_SQUARE = 7,
|
||||
OTBM_TILE_REF = 8,
|
||||
OTBM_SPAWNS = 9,
|
||||
OTBM_SPAWN_AREA = 10,
|
||||
OTBM_MONSTER = 11,
|
||||
OTBM_TOWNS = 12,
|
||||
OTBM_TOWN = 13,
|
||||
OTBM_HOUSETILE = 14,
|
||||
OTBM_WAYPOINTS = 15,
|
||||
OTBM_WAYPOINT = 16
|
||||
};
|
||||
|
||||
enum {
|
||||
OTCM_SIGNATURE = 0x4D43544F,
|
||||
OTCM_VERSION = 1
|
||||
};
|
||||
|
||||
enum {
|
||||
BLOCK_SIZE = 32
|
||||
};
|
||||
|
||||
class TileBlock {
|
||||
public:
|
||||
TileBlock() { m_tiles.fill(nullptr); }
|
||||
|
||||
const TilePtr& create(const Position& pos) {
|
||||
TilePtr& tile = m_tiles[getTileIndex(pos)];
|
||||
tile = TilePtr(new Tile(pos));
|
||||
return tile;
|
||||
}
|
||||
const TilePtr& getOrCreate(const Position& pos) {
|
||||
TilePtr& tile = m_tiles[getTileIndex(pos)];
|
||||
if(!tile)
|
||||
tile = TilePtr(new Tile(pos));
|
||||
return tile;
|
||||
}
|
||||
const TilePtr& get(const Position& pos) { return m_tiles[getTileIndex(pos)]; }
|
||||
void remove(const Position& pos) { m_tiles[getTileIndex(pos)] = nullptr; }
|
||||
|
||||
uint getTileIndex(const Position& pos) { return ((pos.y % BLOCK_SIZE) * BLOCK_SIZE) + (pos.x % BLOCK_SIZE); }
|
||||
|
||||
const std::array<TilePtr, BLOCK_SIZE*BLOCK_SIZE>& getTiles() const { return m_tiles; }
|
||||
|
||||
private:
|
||||
std::array<TilePtr, BLOCK_SIZE*BLOCK_SIZE> m_tiles;
|
||||
};
|
||||
|
||||
//@bindsingleton g_map
|
||||
class Map
|
||||
{
|
||||
public:
|
||||
void terminate();
|
||||
|
||||
void addMapView(const MapViewPtr& mapView);
|
||||
void removeMapView(const MapViewPtr& mapView);
|
||||
void notificateTileUpdateToMapViews(const Position& pos);
|
||||
|
||||
bool loadOtcm(const std::string& fileName);
|
||||
void saveOtcm(const std::string& fileName);
|
||||
|
||||
void loadOtbm(const std::string& fileName, const UIWidgetPtr& pbar = 0);
|
||||
void saveOtbm(const std::string& fileName, const UIWidgetPtr& pbar = 0);
|
||||
|
||||
// otbm attributes (description, size, etc.)
|
||||
void setHouseFile(const std::string& file) { m_attribs.set(OTBM_ATTR_HOUSE_FILE, file); }
|
||||
void setSpawnFile(const std::string& file) { m_attribs.set(OTBM_ATTR_SPAWN_FILE, file); }
|
||||
void setDescription(const std::string& desc) { m_attribs.set(OTBM_ATTR_DESCRIPTION, desc); }
|
||||
void setWidth(uint16 w) { m_attribs.set(OTBM_ATTR_WIDTH, w); }
|
||||
void setHeight(uint16 h) { m_attribs.set(OTBM_ATTR_HEIGHT, h); }
|
||||
|
||||
std::string getHouseFile() { return m_attribs.get<std::string>(OTBM_ATTR_HOUSE_FILE); }
|
||||
std::string getSpawnFile() { return m_attribs.get<std::string>(OTBM_ATTR_SPAWN_FILE); }
|
||||
Size getSize() { return Size(m_attribs.get<uint16>(OTBM_ATTR_WIDTH), m_attribs.get<uint16>(OTBM_ATTR_HEIGHT)); }
|
||||
std::vector<std::string> getDescriptions() { return stdext::split(m_attribs.get<std::string>(OTBM_ATTR_DESCRIPTION), "\n"); }
|
||||
|
||||
void clean();
|
||||
void cleanDynamicThings();
|
||||
void cleanTexts();
|
||||
|
||||
// thing related
|
||||
void addThing(const ThingPtr& thing, const Position& pos, int stackPos = -1);
|
||||
ThingPtr getThing(const Position& pos, int stackPos);
|
||||
bool removeThing(const ThingPtr& thing);
|
||||
bool removeThingByPos(const Position& pos, int stackPos);
|
||||
|
||||
// tile related
|
||||
const TilePtr& createTile(const Position& pos);
|
||||
template <typename... Items>
|
||||
const TilePtr& createTileEx(const Position& pos, const Items&... items);
|
||||
const TilePtr& getOrCreateTile(const Position& pos);
|
||||
const TilePtr& getTile(const Position& pos);
|
||||
void cleanTile(const Position& pos);
|
||||
|
||||
// known creature related
|
||||
void addCreature(const CreaturePtr& creature);
|
||||
CreaturePtr getCreatureById(uint32 id);
|
||||
void removeCreatureById(uint32 id);
|
||||
std::vector<CreaturePtr> getSpectators(const Position& centerPos, bool multiFloor);
|
||||
std::vector<CreaturePtr> getSpectatorsInRange(const Position& centerPos, bool multiFloor, int xRange, int yRange);
|
||||
std::vector<CreaturePtr> getSpectatorsInRangeEx(const Position& centerPos, bool multiFloor, int minXRange, int maxXRange, int minYRange, int maxYRange);
|
||||
|
||||
void setLight(const Light& light) { m_light = light; }
|
||||
void setCentralPosition(const Position& centralPosition);
|
||||
|
||||
bool isLookPossible(const Position& pos);
|
||||
bool isCovered(const Position& pos, int firstFloor = 0);
|
||||
bool isCompletelyCovered(const Position& pos, int firstFloor = 0);
|
||||
bool isAwareOfPosition(const Position& pos);
|
||||
|
||||
Light getLight() { return m_light; }
|
||||
Position getCentralPosition() { return m_centralPosition; }
|
||||
int getFirstAwareFloor();
|
||||
int getLastAwareFloor();
|
||||
const std::vector<MissilePtr>& getFloorMissiles(int z) { return m_floorMissiles[z]; }
|
||||
|
||||
std::vector<AnimatedTextPtr> getAnimatedTexts() { return m_animatedTexts; }
|
||||
std::vector<StaticTextPtr> getStaticTexts() { return m_staticTexts; }
|
||||
|
||||
std::tuple<std::vector<Otc::Direction>, Otc::PathFindResult> findPath(const Position& start, const Position& goal, int maxSteps, int flags = 0);
|
||||
|
||||
private:
|
||||
uint getBlockIndex(const Position& pos) { return ((pos.y / BLOCK_SIZE) * (65536 / BLOCK_SIZE)) + (pos.x / BLOCK_SIZE); }
|
||||
|
||||
std::unordered_map<uint, TileBlock> m_tileBlocks[Otc::MAX_Z+1];
|
||||
std::unordered_map<uint32, CreaturePtr> m_knownCreatures;
|
||||
std::array<std::vector<MissilePtr>, Otc::MAX_Z+1> m_floorMissiles;
|
||||
std::vector<AnimatedTextPtr> m_animatedTexts;
|
||||
std::vector<StaticTextPtr> m_staticTexts;
|
||||
std::vector<MapViewPtr> m_mapViews;
|
||||
std::unordered_map<Position, std::string, PositionHasher> m_waypoints;
|
||||
|
||||
Light m_light;
|
||||
Position m_centralPosition;
|
||||
Rect m_tilesRect;
|
||||
|
||||
stdext::packed_storage<uint8> m_attribs;
|
||||
static TilePtr m_nulltile;
|
||||
};
|
||||
|
||||
extern Map g_map;
|
||||
|
||||
#endif
|
||||
524
src/client/mapio.cpp
Normal file
524
src/client/mapio.cpp
Normal file
@@ -0,0 +1,524 @@
|
||||
/*
|
||||
* Copyright (c) 2010-2013 OTClient <https://github.com/edubart/otclient>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "map.h"
|
||||
#include "tile.h"
|
||||
#include "game.h"
|
||||
|
||||
#include <framework/core/application.h>
|
||||
#include <framework/core/eventdispatcher.h>
|
||||
#include <framework/core/resourcemanager.h>
|
||||
#include <framework/core/filestream.h>
|
||||
#include <framework/core/binarytree.h>
|
||||
#include <framework/xml/tinyxml.h>
|
||||
#include <framework/ui/uiwidget.h>
|
||||
|
||||
void Map::loadOtbm(const std::string& fileName, const UIWidgetPtr& pbar)
|
||||
{
|
||||
FileStreamPtr fin = g_resources.openFile(fileName);
|
||||
if(!fin)
|
||||
stdext::throw_exception(stdext::format("Unable to load map '%s'", fileName));
|
||||
|
||||
fin->cache();
|
||||
if(!g_things.isOtbLoaded())
|
||||
stdext::throw_exception("OTB isn't loaded yet to load a map.");
|
||||
|
||||
if(fin->getU32())
|
||||
stdext::throw_exception("Unknown file version detected");
|
||||
|
||||
BinaryTreePtr root = fin->getBinaryTree();
|
||||
if(root->getU8())
|
||||
stdext::throw_exception("could not read root property!");
|
||||
|
||||
uint32 headerVersion = root->getU32();
|
||||
if(headerVersion > 3)
|
||||
stdext::throw_exception(stdext::format("Unknown OTBM version detected: %u.", headerVersion));
|
||||
|
||||
setWidth(root->getU16());
|
||||
setHeight(root->getU16());
|
||||
|
||||
uint32 headerMajorItems = root->getU8();
|
||||
if(headerMajorItems > g_things.getOtbMajorVersion()) {
|
||||
stdext::throw_exception(stdext::format("This map was saved with different OTB version. read %d what it's supposed to be: %d",
|
||||
headerMajorItems, g_things.getOtbMajorVersion()));
|
||||
}
|
||||
|
||||
root->skip(3);
|
||||
uint32 headerMinorItems = root->getU32();
|
||||
if(headerMinorItems > g_things.getOtbMinorVersion()) {
|
||||
g_logger.warning(stdext::format("This map needs an updated OTB. read %d what it's supposed to be: %d or less",
|
||||
headerMinorItems, g_things.getOtbMinorVersion()));
|
||||
}
|
||||
|
||||
BinaryTreePtr node = root->getChildren()[0];
|
||||
if(node->getU8() != OTBM_MAP_DATA)
|
||||
stdext::throw_exception("Could not read root data node");
|
||||
|
||||
while (node->canRead()) {
|
||||
uint8 attribute = node->getU8();
|
||||
std::string tmp = node->getString();
|
||||
switch (attribute) {
|
||||
case OTBM_ATTR_DESCRIPTION:
|
||||
setDescription(tmp);
|
||||
break;
|
||||
case OTBM_ATTR_SPAWN_FILE:
|
||||
setSpawnFile(fileName.substr(0, fileName.rfind('/') + 1) + tmp);
|
||||
break;
|
||||
case OTBM_ATTR_HOUSE_FILE:
|
||||
setHouseFile(fileName.substr(0, fileName.rfind('/') + 1) + tmp);
|
||||
break;
|
||||
default:
|
||||
stdext::throw_exception(stdext::format("Invalid attribute '%d'", (int)attribute));
|
||||
}
|
||||
}
|
||||
|
||||
for(const BinaryTreePtr& nodeMapData : node->getChildren()) {
|
||||
uint8 mapDataType = nodeMapData->getU8();
|
||||
if(mapDataType == OTBM_TILE_AREA) {
|
||||
Position basePos = nodeMapData->getPosition();
|
||||
unsigned int pbarvalue=0;
|
||||
|
||||
for(const BinaryTreePtr &nodeTile : nodeMapData->getChildren()) {
|
||||
uint8 type = nodeTile->getU8();
|
||||
if(type != OTBM_TILE && type != OTBM_HOUSETILE)
|
||||
stdext::throw_exception(stdext::format("invalid node tile type %d", (int)type));
|
||||
|
||||
HousePtr house = nullptr;
|
||||
uint32 flags = TILESTATE_NONE;
|
||||
Position pos = basePos + nodeTile->getPoint();
|
||||
|
||||
if(type == OTBM_HOUSETILE) {
|
||||
uint32 hId = nodeTile->getU32();
|
||||
TilePtr tile = getOrCreateTile(pos);
|
||||
if(!(house = g_houses.getHouse(hId))) {
|
||||
house = HousePtr(new House(hId));
|
||||
g_houses.addHouse(house);
|
||||
}
|
||||
house->setTile(tile);
|
||||
}
|
||||
|
||||
while(nodeTile->canRead()) {
|
||||
uint8 tileAttr = nodeTile->getU8();
|
||||
switch (tileAttr) {
|
||||
case OTBM_ATTR_TILE_FLAGS: {
|
||||
uint32 _flags = nodeTile->getU32();
|
||||
if((_flags & TILESTATE_PROTECTIONZONE) == TILESTATE_PROTECTIONZONE)
|
||||
flags |= TILESTATE_PROTECTIONZONE;
|
||||
else if((_flags & TILESTATE_OPTIONALZONE) == TILESTATE_OPTIONALZONE)
|
||||
flags |= TILESTATE_OPTIONALZONE;
|
||||
else if((_flags & TILESTATE_HARDCOREZONE) == TILESTATE_HARDCOREZONE)
|
||||
flags |= TILESTATE_HARDCOREZONE;
|
||||
|
||||
if((_flags & TILESTATE_NOLOGOUT) == TILESTATE_NOLOGOUT)
|
||||
flags |= TILESTATE_NOLOGOUT;
|
||||
|
||||
if((_flags & TILESTATE_REFRESH) == TILESTATE_REFRESH)
|
||||
flags |= TILESTATE_REFRESH;
|
||||
|
||||
break;
|
||||
}
|
||||
case OTBM_ATTR_ITEM: {
|
||||
addThing(Item::createFromOtb(nodeTile->getU16()), pos);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
stdext::throw_exception(stdext::format("invalid tile attribute %d at pos %s",
|
||||
(int)tileAttr, stdext::to_string(pos)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for(const BinaryTreePtr& nodeItem : nodeTile->getChildren()) {
|
||||
if(nodeItem->getU8() != OTBM_ITEM)
|
||||
stdext::throw_exception("invalid item node");
|
||||
|
||||
ItemPtr item = Item::createFromOtb(nodeItem->getU16());
|
||||
item->unserializeItem(nodeItem);
|
||||
|
||||
if(item->isContainer()) {
|
||||
for(const BinaryTreePtr& containerItem : nodeItem->getChildren()) {
|
||||
if(containerItem->getU8() != OTBM_ITEM)
|
||||
stdext::throw_exception("invalid container item node");
|
||||
|
||||
ItemPtr cItem = Item::createFromOtb(containerItem->getU16());
|
||||
cItem->unserializeItem(containerItem);
|
||||
item->addContainerItem(cItem);
|
||||
}
|
||||
}
|
||||
|
||||
if(house && item->isMoveable()) {
|
||||
g_logger.warning(stdext::format("Movable item found in house: %d at pos %s - escaping...", item->getId(), stdext::to_string(pos)));
|
||||
item.reset();
|
||||
}
|
||||
|
||||
addThing(item, pos);
|
||||
}
|
||||
|
||||
if(const TilePtr& tile = getTile(pos)) {
|
||||
if(house)
|
||||
tile->setHouseId(house->getId());
|
||||
tile->setFlags((tileflags_t)flags);
|
||||
//if(!(++pbarvalue % 8192) && pbar);
|
||||
}
|
||||
}
|
||||
} else if(mapDataType == OTBM_TOWNS) {
|
||||
TownPtr town = nullptr;
|
||||
for(const BinaryTreePtr &nodeTown : nodeMapData->getChildren()) {
|
||||
if(nodeTown->getU8() != OTBM_TOWN)
|
||||
stdext::throw_exception("invalid town node.");
|
||||
|
||||
uint32 townId = nodeTown->getU32();
|
||||
std::string townName = nodeTown->getString();
|
||||
Position townCoords = nodeTown->getPosition();
|
||||
if(!(town = g_towns.getTown(townId))) {
|
||||
town = TownPtr(new Town(townId, townName, townCoords));
|
||||
g_towns.addTown(town);
|
||||
}
|
||||
}
|
||||
} else if(mapDataType == OTBM_WAYPOINTS && headerVersion > 1) {
|
||||
for(const BinaryTreePtr &nodeWaypoint : nodeMapData->getChildren()) {
|
||||
if(nodeWaypoint->getU8() != OTBM_WAYPOINT)
|
||||
stdext::throw_exception("invalid waypoint node.");
|
||||
|
||||
std::string name = nodeWaypoint->getString();
|
||||
Position waypointPos = nodeWaypoint->getPosition();
|
||||
if(waypointPos.isValid() && !name.empty() && m_waypoints.find(waypointPos) == m_waypoints.end())
|
||||
m_waypoints.insert(std::make_pair(waypointPos, name));
|
||||
}
|
||||
} else
|
||||
stdext::throw_exception(stdext::format("Unknown map data node %d", (int)mapDataType));
|
||||
}
|
||||
|
||||
fin->close();
|
||||
}
|
||||
|
||||
void Map::saveOtbm(const std::string& fileName, const UIWidgetPtr&/* pbar*/)
|
||||
{
|
||||
FileStreamPtr fin = g_resources.createFile(fileName);
|
||||
if(!fin)
|
||||
stdext::throw_exception(stdext::format("failed to open file '%s' for write", fileName));
|
||||
|
||||
fin->cache();
|
||||
std::string dir;
|
||||
if(fileName.find_last_of('/') == std::string::npos)
|
||||
dir = g_resources.getWorkDir();
|
||||
else
|
||||
dir = fileName.substr(0, fileName.find_last_of('/'));
|
||||
|
||||
uint32 version = 0;
|
||||
if(g_things.getOtbMajorVersion() < ClientVersion820)
|
||||
version = 1;
|
||||
else
|
||||
version = 2;
|
||||
|
||||
/// Usually when a map has empty house/spawn file it means the map is new.
|
||||
/// TODO: Ask the user for a map name instead of those ugly uses of substr
|
||||
std::string::size_type sep_pos;
|
||||
std::string houseFile = getHouseFile();
|
||||
std::string spawnFile = getSpawnFile();
|
||||
std::string cpyf;
|
||||
|
||||
if((sep_pos = fileName.rfind('.')) != std::string::npos && stdext::ends_with(fileName, ".otbm"))
|
||||
cpyf = fileName.substr(0, sep_pos);
|
||||
|
||||
if(houseFile.empty())
|
||||
houseFile = cpyf + "-houses.xml";
|
||||
|
||||
if(spawnFile.empty())
|
||||
spawnFile = cpyf + "-spawns.xml";
|
||||
|
||||
/// we only need the filename to save to, the directory should be resolved by the OTBM loader not here
|
||||
if((sep_pos = spawnFile.rfind('/')) != std::string::npos)
|
||||
spawnFile = spawnFile.substr(sep_pos + 1);
|
||||
|
||||
if((sep_pos = houseFile.rfind('/')) != std::string::npos)
|
||||
houseFile = houseFile.substr(sep_pos + 1);
|
||||
|
||||
fin->addU32(0); // file version
|
||||
OutputBinaryTreePtr root(new OutputBinaryTree(fin));
|
||||
{
|
||||
root->addU32(version);
|
||||
|
||||
Size mapSize = getSize();
|
||||
root->addU16(mapSize.width());
|
||||
root->addU16(mapSize.height());
|
||||
|
||||
root->addU32(g_things.getOtbMajorVersion());
|
||||
root->addU32(g_things.getOtbMinorVersion());
|
||||
|
||||
root->startNode(OTBM_MAP_DATA);
|
||||
{
|
||||
// own description.
|
||||
for(const auto& desc : getDescriptions()) {
|
||||
root->addU8(OTBM_ATTR_DESCRIPTION);
|
||||
root->addString(desc);
|
||||
}
|
||||
|
||||
// special one
|
||||
root->addU8(OTBM_ATTR_DESCRIPTION);
|
||||
root->addString(stdext::format("Saved with %s v%s", g_app.getName(), g_app.getVersion()));
|
||||
|
||||
// spawn file.
|
||||
root->addU8(OTBM_ATTR_SPAWN_FILE);
|
||||
root->addString(spawnFile);
|
||||
|
||||
// house file.
|
||||
if(version > 1) {
|
||||
root->addU8(OTBM_ATTR_HOUSE_FILE);
|
||||
root->addString(houseFile);
|
||||
}
|
||||
|
||||
int px = -1, py = -1, pz =-1;
|
||||
bool firstNode = true;
|
||||
|
||||
for(uint8_t z = 0; z <= Otc::MAX_Z; ++z) {
|
||||
for(const auto& it : m_tileBlocks[z]) {
|
||||
const TileBlock& block = it.second;
|
||||
for(const TilePtr& tile : block.getTiles()) {
|
||||
if(!tile || tile->isEmpty())
|
||||
continue;
|
||||
|
||||
const Position& pos = tile->getPosition();
|
||||
if(!pos.isValid())
|
||||
continue;
|
||||
|
||||
if(pos.x < px || pos.x >= px + 256
|
||||
|| pos.y < py || pos.y >= py + 256
|
||||
|| pos.z != pz) {
|
||||
if(!firstNode)
|
||||
root->endNode(); /// OTBM_TILE_AREA
|
||||
|
||||
firstNode = false;
|
||||
root->startNode(OTBM_TILE_AREA);
|
||||
|
||||
px = pos.x & 0xFF00;
|
||||
py = pos.y & 0xFF00;
|
||||
pz = pos.z;
|
||||
root->addPos(Position(px, py, pz));
|
||||
}
|
||||
|
||||
root->startNode(tile->isHouseTile() ? OTBM_HOUSETILE : OTBM_TILE);
|
||||
root->addPoint(Point(pos.x, pos.y) & 0xFF);
|
||||
if(tile->isHouseTile())
|
||||
root->addU32(tile->getHouseId());
|
||||
|
||||
if(tile->getFlags()) {
|
||||
root->addU8(OTBM_ATTR_TILE_FLAGS);
|
||||
root->addU32(tile->getFlags());
|
||||
}
|
||||
|
||||
const auto& itemList = tile->getItems();
|
||||
const ItemPtr& ground = tile->getGround();
|
||||
if(ground) {
|
||||
// Those types are called "complex" needs other stuff to be written.
|
||||
// For containers, there is container items, for depot, depot it and so on.
|
||||
if(!ground->isContainer() && !ground->isDepot()
|
||||
&& !ground->isDoor() && !ground->isTeleport()) {
|
||||
root->addU8(OTBM_ATTR_ITEM);
|
||||
root->addU16(ground->getServerId());
|
||||
} else
|
||||
ground->serializeItem(root);
|
||||
}
|
||||
for(const ItemPtr& item : itemList)
|
||||
if(!item->isGround())
|
||||
item->serializeItem(root);
|
||||
|
||||
root->endNode(); // OTBM_TILE
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!firstNode)
|
||||
root->endNode(); // OTBM_TILE_AREA
|
||||
|
||||
root->startNode(OTBM_TOWNS);
|
||||
for(const TownPtr& town : g_towns.getTowns()) {
|
||||
root->addU32(town->getId());
|
||||
root->addString(town->getName());
|
||||
root->addPos(town->getPos());
|
||||
}
|
||||
root->endNode();
|
||||
|
||||
if(version > 1) {
|
||||
root->startNode(OTBM_WAYPOINTS);
|
||||
for(const auto& it : m_waypoints) {
|
||||
root->addString(it.second);
|
||||
root->addPos(it.first);
|
||||
}
|
||||
root->endNode();
|
||||
}
|
||||
}
|
||||
root->endNode(); // OTBM_MAP_DATA
|
||||
}
|
||||
root->endNode();
|
||||
|
||||
fin->flush();
|
||||
fin->close();
|
||||
}
|
||||
|
||||
bool Map::loadOtcm(const std::string& fileName)
|
||||
{
|
||||
try {
|
||||
FileStreamPtr fin = g_resources.openFile(fileName);
|
||||
if(!fin)
|
||||
stdext::throw_exception("unable to open file");
|
||||
|
||||
stdext::timer loadTimer;
|
||||
fin->cache();
|
||||
|
||||
uint32 signature = fin->getU32();
|
||||
if(signature != OTCM_SIGNATURE)
|
||||
stdext::throw_exception("invalid otcm file");
|
||||
|
||||
uint16 start = fin->getU16();
|
||||
uint16 version = fin->getU16();
|
||||
fin->getU32(); // flags
|
||||
|
||||
switch(version) {
|
||||
case 1: {
|
||||
fin->getString(); // description
|
||||
uint32 datSignature = fin->getU32();
|
||||
fin->getU16(); // protocol version
|
||||
fin->getString(); // world name
|
||||
|
||||
if(datSignature != g_things.getDatSignature())
|
||||
g_logger.warning("otcm map loaded was created with a different dat signature");
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
stdext::throw_exception("otcm version not supported");
|
||||
}
|
||||
|
||||
fin->seek(start);
|
||||
|
||||
while(true) {
|
||||
Position pos;
|
||||
|
||||
pos.x = fin->getU16();
|
||||
pos.y = fin->getU16();
|
||||
pos.z = fin->getU8();
|
||||
|
||||
// end of file
|
||||
if(!pos.isValid())
|
||||
break;
|
||||
|
||||
const TilePtr& tile = g_map.createTile(pos);
|
||||
|
||||
int stackPos = 0;
|
||||
while(true) {
|
||||
int id = fin->getU16();
|
||||
|
||||
// end of tile
|
||||
if(id == 0xFFFF)
|
||||
break;
|
||||
|
||||
int countOrSubType = fin->getU8();
|
||||
|
||||
ItemPtr item = Item::create(id);
|
||||
item->setCountOrSubType(countOrSubType);
|
||||
|
||||
if(item->isValid())
|
||||
tile->addThing(item, stackPos++);
|
||||
}
|
||||
}
|
||||
|
||||
fin->close();
|
||||
|
||||
// well, this is really slow
|
||||
g_logger.debug(stdext::format("Otcm load time: %.2f seconds", loadTimer.elapsed_seconds()));
|
||||
return true;
|
||||
} catch(stdext::exception& e) {
|
||||
g_logger.error(stdext::format("failed to load OTCM map: %s", e.what()));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void Map::saveOtcm(const std::string& fileName)
|
||||
{
|
||||
try {
|
||||
stdext::timer saveTimer;
|
||||
|
||||
FileStreamPtr fin = g_resources.createFile(fileName);
|
||||
fin->cache();
|
||||
|
||||
//TODO: compression flag with zlib
|
||||
uint32 flags = 0;
|
||||
|
||||
// header
|
||||
fin->addU32(OTCM_SIGNATURE);
|
||||
fin->addU16(0); // data start, will be overwritten later
|
||||
fin->addU16(OTCM_VERSION);
|
||||
fin->addU32(flags);
|
||||
|
||||
// version 1 header
|
||||
fin->addString("OTCM 1.0"); // map description
|
||||
fin->addU32(g_things.getDatSignature());
|
||||
fin->addU16(g_game.getProtocolVersion());
|
||||
fin->addString(g_game.getWorldName());
|
||||
|
||||
// go back and rewrite where the map data starts
|
||||
uint32 start = fin->tell();
|
||||
fin->seek(4);
|
||||
fin->addU16(start);
|
||||
fin->seek(start);
|
||||
|
||||
for(uint8_t z = 0; z <= Otc::MAX_Z; ++z) {
|
||||
for(const auto& it : m_tileBlocks[z]) {
|
||||
const TileBlock& block = it.second;
|
||||
for(const TilePtr& tile : block.getTiles()) {
|
||||
if(!tile || tile->isEmpty())
|
||||
continue;
|
||||
|
||||
Position pos = tile->getPosition();
|
||||
fin->addU16(pos.x);
|
||||
fin->addU16(pos.y);
|
||||
fin->addU8(pos.z);
|
||||
|
||||
for(const ThingPtr& thing : tile->getThings()) {
|
||||
if(thing->isItem()) {
|
||||
ItemPtr item = thing->static_self_cast<Item>();
|
||||
fin->addU16(item->getId());
|
||||
fin->addU8(item->getCountOrSubType());
|
||||
}
|
||||
}
|
||||
|
||||
// end of tile
|
||||
fin->addU16(0xFFFF);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// end of file
|
||||
Position invalidPos;
|
||||
fin->addU16(invalidPos.x);
|
||||
fin->addU16(invalidPos.y);
|
||||
fin->addU8(invalidPos.z);
|
||||
|
||||
fin->flush();
|
||||
|
||||
fin->close();
|
||||
//g_logger.debug(stdext::format("Otcm save time: %.2f seconds", saveTimer.elapsed_seconds()));
|
||||
} catch(stdext::exception& e) {
|
||||
g_logger.error(stdext::format("failed to save OTCM map: %s", e.what()));
|
||||
}
|
||||
}
|
||||
668
src/client/mapview.cpp
Normal file
668
src/client/mapview.cpp
Normal file
@@ -0,0 +1,668 @@
|
||||
/*
|
||||
* Copyright (c) 2010-2013 OTClient <https://github.com/edubart/otclient>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "mapview.h"
|
||||
|
||||
#include "creature.h"
|
||||
#include "map.h"
|
||||
#include "tile.h"
|
||||
#include "statictext.h"
|
||||
#include "animatedtext.h"
|
||||
#include "missile.h"
|
||||
#include "shadermanager.h"
|
||||
#include "lightview.h"
|
||||
|
||||
#include <framework/graphics/graphics.h>
|
||||
#include <framework/graphics/image.h>
|
||||
#include <framework/graphics/framebuffermanager.h>
|
||||
#include <framework/core/eventdispatcher.h>
|
||||
#include <framework/core/application.h>
|
||||
#include <framework/core/resourcemanager.h>
|
||||
|
||||
|
||||
enum {
|
||||
// 3840x2160 => 1080p optimized
|
||||
// 2560x1440 => 720p optimized
|
||||
// 1728x972 => 480p optimized
|
||||
|
||||
NEAR_VIEW_AREA = 32*32,
|
||||
MID_VIEW_AREA = 64*64,
|
||||
FAR_VIEW_AREA = 128*128,
|
||||
MAX_TILE_DRAWS = NEAR_VIEW_AREA*7
|
||||
};
|
||||
|
||||
MapView::MapView()
|
||||
{
|
||||
m_viewMode = NEAR_VIEW;
|
||||
m_lockedFirstVisibleFloor = -1;
|
||||
m_cachedFirstVisibleFloor = 7;
|
||||
m_cachedLastVisibleFloor = 7;
|
||||
m_updateTilesPos = 0;
|
||||
m_minimumAmbientLight = 0;
|
||||
m_optimizedSize = Size(Otc::AWARE_X_TILES, Otc::AWARE_Y_TILES) * Otc::TILE_PIXELS;
|
||||
|
||||
m_framebuffer = g_framebuffers.createFrameBuffer();
|
||||
setVisibleDimension(Size(15, 11));
|
||||
|
||||
m_shader = g_shaders.getDefaultMapShader();
|
||||
}
|
||||
|
||||
MapView::~MapView()
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
assert(!g_app.isTerminated());
|
||||
#endif
|
||||
}
|
||||
|
||||
void MapView::draw(const Rect& rect)
|
||||
{
|
||||
// update visible tiles cache when needed
|
||||
if(m_mustUpdateVisibleTilesCache || m_updateTilesPos > 0)
|
||||
updateVisibleTilesCache(m_mustUpdateVisibleTilesCache ? 0 : m_updateTilesPos);
|
||||
|
||||
float scaleFactor = m_tileSize/(float)Otc::TILE_PIXELS;
|
||||
Position cameraPosition = getCameraPosition();
|
||||
|
||||
int drawFlags = 0;
|
||||
if(m_viewMode == NEAR_VIEW)
|
||||
drawFlags = Otc::DrawGround | Otc::DrawGroundBorders | Otc::DrawWalls |
|
||||
Otc::DrawItems | Otc::DrawCreatures | Otc::DrawEffects | Otc::DrawMissiles | Otc::DrawAnimations;
|
||||
else
|
||||
drawFlags = Otc::DrawGround | Otc::DrawGroundBorders | Otc::DrawWalls | Otc::DrawItems;
|
||||
|
||||
Size tileSize = Size(1,1) * m_tileSize;
|
||||
|
||||
if(m_mustDrawVisibleTilesCache || (drawFlags & Otc::DrawAnimations)) {
|
||||
m_framebuffer->bind();
|
||||
|
||||
if(m_mustCleanFramebuffer) {
|
||||
Rect clearRect = Rect(0, 0, m_drawDimension * m_tileSize);
|
||||
g_painter->setColor(Color::black);
|
||||
g_painter->drawFilledRect(clearRect);
|
||||
|
||||
if(m_drawLights) {
|
||||
m_lightView->reset();
|
||||
m_lightView->resize(m_framebuffer->getSize());
|
||||
|
||||
Light ambientLight;
|
||||
if(cameraPosition.z <= Otc::SEA_FLOOR) {
|
||||
ambientLight = g_map.getLight();
|
||||
} else {
|
||||
ambientLight.color = 215;
|
||||
ambientLight.intensity = 0;
|
||||
}
|
||||
ambientLight.intensity = std::max<int>(m_minimumAmbientLight*255, ambientLight.intensity);
|
||||
m_lightView->setGlobalLight(ambientLight);
|
||||
}
|
||||
}
|
||||
g_painter->setColor(Color::white);
|
||||
|
||||
auto it = m_cachedVisibleTiles.begin();
|
||||
auto end = m_cachedVisibleTiles.end();
|
||||
for(int z=m_cachedLastVisibleFloor;z>=m_cachedFirstVisibleFloor;--z) {
|
||||
|
||||
while(it != end) {
|
||||
const TilePtr& tile = *it;
|
||||
Position tilePos = tile->getPosition();
|
||||
if(tilePos.z != z)
|
||||
break;
|
||||
else
|
||||
++it;
|
||||
|
||||
if(!m_drawMinimapColors)
|
||||
tile->draw(transformPositionTo2D(tilePos, cameraPosition), scaleFactor, drawFlags, m_lightView.get());
|
||||
else {
|
||||
uint8 c = tile->getMinimapColorByte();
|
||||
if(c == 0)
|
||||
continue;
|
||||
|
||||
g_painter->setColor(Color::from8bit(c));
|
||||
g_painter->drawFilledRect(Rect(transformPositionTo2D(tilePos, cameraPosition), tileSize));
|
||||
}
|
||||
}
|
||||
|
||||
if(drawFlags & Otc::DrawMissiles && !m_drawMinimapColors) {
|
||||
for(const MissilePtr& missile : g_map.getFloorMissiles(z)) {
|
||||
missile->draw(transformPositionTo2D(missile->getPosition(), cameraPosition), scaleFactor, drawFlags & Otc::DrawAnimations, m_lightView.get());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_framebuffer->release();
|
||||
|
||||
// generating mipmaps each frame can be slow in older cards
|
||||
//m_framebuffer->getTexture()->buildHardwareMipmaps();
|
||||
|
||||
m_mustDrawVisibleTilesCache = false;
|
||||
}
|
||||
|
||||
Point drawOffset = ((m_drawDimension - m_visibleDimension - Size(1,1)).toPoint()/2) * m_tileSize;
|
||||
if(isFollowingCreature())
|
||||
drawOffset += m_followingCreature->getWalkOffset() * scaleFactor;
|
||||
|
||||
Size srcSize = rect.size();
|
||||
Size srcVisible = m_visibleDimension * m_tileSize;
|
||||
srcSize.scale(srcVisible, Fw::KeepAspectRatio);
|
||||
drawOffset.x += (srcVisible.width() - srcSize.width()) / 2;
|
||||
drawOffset.y += (srcVisible.height() - srcSize.height()) / 2;
|
||||
Rect srcRect = Rect(drawOffset, srcSize);
|
||||
|
||||
g_painter->setColor(Color::white);
|
||||
glDisable(GL_BLEND);
|
||||
g_painter->setShaderProgram(m_shader);
|
||||
#if 0
|
||||
// debug source area
|
||||
g_painter->saveAndResetState();
|
||||
m_framebuffer->bind();
|
||||
g_painter->setColor(Color::green);
|
||||
g_painter->drawBoundingRect(srcRect, 2);
|
||||
m_framebuffer->release();
|
||||
g_painter->restoreSavedState();
|
||||
m_framebuffer->draw(rect);
|
||||
#else
|
||||
m_framebuffer->draw(rect, srcRect);
|
||||
#endif
|
||||
g_painter->resetShaderProgram();
|
||||
glEnable(GL_BLEND);
|
||||
|
||||
|
||||
// this could happen if the player position is not known yet
|
||||
if(!cameraPosition.isValid())
|
||||
return;
|
||||
|
||||
float horizontalStretchFactor = rect.width() / (float)srcRect.width();
|
||||
float verticalStretchFactor = rect.height() / (float)srcRect.height();
|
||||
|
||||
// avoid drawing texts on map in far zoom outs
|
||||
if(m_viewMode == NEAR_VIEW && m_drawTexts) {
|
||||
for(const CreaturePtr& creature : m_cachedFloorVisibleCreatures) {
|
||||
if(!creature->canBeSeen())
|
||||
continue;
|
||||
|
||||
Point creatureOffset = Point(16 - creature->getDisplacementX(), -3 - creature->getDisplacementY());
|
||||
Position pos = creature->getPosition();
|
||||
Point p = transformPositionTo2D(pos, cameraPosition) - drawOffset;
|
||||
p += (creature->getDrawOffset() + creatureOffset) * scaleFactor;
|
||||
p.x = p.x * horizontalStretchFactor;
|
||||
p.y = p.y * verticalStretchFactor;
|
||||
p += rect.topLeft();
|
||||
|
||||
creature->drawInformation(p, g_map.isCovered(pos, m_cachedFirstVisibleFloor), rect);
|
||||
}
|
||||
}
|
||||
|
||||
// lights are drawn after names and before texts
|
||||
if(m_drawLights)
|
||||
m_lightView->draw(rect, srcRect);
|
||||
|
||||
if(m_viewMode == NEAR_VIEW && m_drawTexts) {
|
||||
for(const StaticTextPtr& staticText : g_map.getStaticTexts()) {
|
||||
Position pos = staticText->getPosition();
|
||||
|
||||
// ony draw static texts from current camera floor, unless yells
|
||||
//if(pos.z != cameraPosition.z && !staticText->isYell())
|
||||
// continue;
|
||||
|
||||
Point p = transformPositionTo2D(pos, cameraPosition) - drawOffset;
|
||||
p.x = p.x * horizontalStretchFactor;
|
||||
p.y = p.y * verticalStretchFactor;
|
||||
p += rect.topLeft();
|
||||
staticText->drawText(p, rect);
|
||||
}
|
||||
|
||||
for(const AnimatedTextPtr& animatedText : g_map.getAnimatedTexts()) {
|
||||
Position pos = animatedText->getPosition();
|
||||
|
||||
// only draw animated texts from visible floors
|
||||
if(pos.z < m_cachedFirstVisibleFloor || pos.z > m_cachedLastVisibleFloor)
|
||||
continue;
|
||||
|
||||
// dont draw animated texts from covered tiles
|
||||
if(pos.z != cameraPosition.z && g_map.isCovered(pos, m_cachedFirstVisibleFloor))
|
||||
continue;
|
||||
|
||||
Point p = transformPositionTo2D(pos, cameraPosition) - drawOffset;
|
||||
p.x = p.x * horizontalStretchFactor;
|
||||
p.y = p.y * verticalStretchFactor;
|
||||
p += rect.topLeft();
|
||||
animatedText->drawText(p, rect);
|
||||
}
|
||||
} else if(m_viewMode > NEAR_VIEW) {
|
||||
// draw a cross in the center instead of our creature
|
||||
/*
|
||||
Known Issue: Changing Z axis causes the cross to go off a little bit.
|
||||
*/
|
||||
Rect vRect(0, 0, 2, 10);
|
||||
Rect hRect(0, 0, 10, 2);
|
||||
g_painter->setColor(Color::white);
|
||||
|
||||
if(!m_follow && m_followingCreature)
|
||||
{
|
||||
Position pos = m_followingCreature->getPosition();
|
||||
Point p = transformPositionTo2D(pos, cameraPosition) - drawOffset;
|
||||
p.x = p.x * horizontalStretchFactor;
|
||||
p.y = p.y * verticalStretchFactor;
|
||||
p += rect.topLeft();
|
||||
|
||||
vRect.setX(p.x); vRect.setY(p.y - 4);
|
||||
hRect.setX(p.x - 4); hRect.setY(p.y);
|
||||
|
||||
hRect.setWidth(10); hRect.setHeight(2);
|
||||
vRect.setWidth(2); vRect.setHeight(10);
|
||||
}
|
||||
else {
|
||||
vRect.moveCenter(rect.center());
|
||||
hRect.moveCenter(rect.center());
|
||||
}
|
||||
|
||||
g_painter->drawFilledRect(vRect);
|
||||
g_painter->drawFilledRect(hRect);
|
||||
}
|
||||
}
|
||||
|
||||
void MapView::updateVisibleTilesCache(int start)
|
||||
{
|
||||
if(start == 0) {
|
||||
m_cachedFirstVisibleFloor = calcFirstVisibleFloor();
|
||||
m_cachedLastVisibleFloor = calcLastVisibleFloor();
|
||||
assert(m_cachedFirstVisibleFloor >= 0 && m_cachedLastVisibleFloor >= 0 &&
|
||||
m_cachedFirstVisibleFloor <= Otc::MAX_Z && m_cachedLastVisibleFloor <= Otc::MAX_Z);
|
||||
|
||||
if(m_cachedLastVisibleFloor < m_cachedFirstVisibleFloor)
|
||||
m_cachedLastVisibleFloor = m_cachedFirstVisibleFloor;
|
||||
|
||||
m_cachedFloorVisibleCreatures.clear();
|
||||
m_cachedVisibleTiles.clear();
|
||||
|
||||
m_mustCleanFramebuffer = true;
|
||||
m_mustDrawVisibleTilesCache = true;
|
||||
m_mustUpdateVisibleTilesCache = false;
|
||||
m_updateTilesPos = 0;
|
||||
} else
|
||||
m_mustCleanFramebuffer = false;
|
||||
|
||||
// there is no tile to render on invalid positions
|
||||
Position cameraPosition = getCameraPosition();
|
||||
if(!cameraPosition.isValid())
|
||||
return;
|
||||
|
||||
bool stop = false;
|
||||
|
||||
// clear current visible tiles cache
|
||||
m_cachedVisibleTiles.clear();
|
||||
m_mustDrawVisibleTilesCache = true;
|
||||
m_updateTilesPos = 0;
|
||||
|
||||
// cache visible tiles in draw order
|
||||
// draw from last floor (the lower) to first floor (the higher)
|
||||
for(int iz = m_cachedLastVisibleFloor; iz >= m_cachedFirstVisibleFloor && !stop; --iz) {
|
||||
if(m_viewMode <= FAR_VIEW) {
|
||||
const int numDiagonals = m_drawDimension.width() + m_drawDimension.height() - 1;
|
||||
// loop through / diagonals beginning at top left and going to top right
|
||||
for(int diagonal = 0; diagonal < numDiagonals && !stop; ++diagonal) {
|
||||
// loop current diagonal tiles
|
||||
int advance = std::max(diagonal - m_drawDimension.height(), 0);
|
||||
for(int iy = diagonal - advance, ix = advance; iy >= 0 && ix < m_drawDimension.width() && !stop; --iy, ++ix) {
|
||||
// only start really looking tiles in the desired start
|
||||
if(m_updateTilesPos < start) {
|
||||
m_updateTilesPos++;
|
||||
continue;
|
||||
}
|
||||
|
||||
// avoid rendering too much tiles at once
|
||||
if((int)m_cachedVisibleTiles.size() > MAX_TILE_DRAWS && m_viewMode >= HUGE_VIEW) {
|
||||
stop = true;
|
||||
break;
|
||||
}
|
||||
|
||||
// position on current floor
|
||||
//TODO: check position limits
|
||||
Position tilePos = cameraPosition.translated(ix - m_virtualCenterOffset.x, iy - m_virtualCenterOffset.y);
|
||||
// adjust tilePos to the wanted floor
|
||||
tilePos.coveredUp(cameraPosition.z - iz);
|
||||
if(const TilePtr& tile = g_map.getTile(tilePos)) {
|
||||
// skip tiles that have nothing
|
||||
if(!tile->isDrawable())
|
||||
continue;
|
||||
// skip tiles that are completely behind another tile
|
||||
if(g_map.isCompletelyCovered(tilePos, m_cachedFirstVisibleFloor))
|
||||
continue;
|
||||
m_cachedVisibleTiles.push_back(tile);
|
||||
}
|
||||
m_updateTilesPos++;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// cache tiles in spiral mode
|
||||
static std::vector<Point> m_spiral;
|
||||
if(start == 0) {
|
||||
m_spiral.resize(m_drawDimension.area());
|
||||
int width = m_drawDimension.width();
|
||||
int height = m_drawDimension.height();
|
||||
int tpx = width/2 - 2;
|
||||
int tpy = height/2 - 2;
|
||||
int count = 0;
|
||||
Rect area(0, 0, m_drawDimension);
|
||||
m_spiral[count++] = Point(tpx+1,tpy+1);
|
||||
for(int step = 1; tpx >= 0 || tpy >= 0; ++step, --tpx, --tpy) {
|
||||
int qs = 2*step;
|
||||
Rect lines[4] = {
|
||||
Rect(tpx, tpy, qs, 1),
|
||||
Rect(tpx + qs, tpy, 1, qs),
|
||||
Rect(tpx + 1, tpy + qs, qs, 1),
|
||||
Rect(tpx, tpy + 1, 1, qs),
|
||||
};
|
||||
|
||||
for(int i=0;i<4;++i) {
|
||||
int sx = std::max(lines[i].left(), area.left());
|
||||
int ex = std::min(lines[i].right(), area.right());
|
||||
int sy = std::max(lines[i].top(), area.top());
|
||||
int ey = std::min(lines[i].bottom(), area.bottom());
|
||||
for(int qx=sx;qx<=ex;++qx)
|
||||
for(int qy=sy;qy<=ey;++qy)
|
||||
m_spiral[count++] = Point(qx, qy);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for(m_updateTilesPos = start; m_updateTilesPos < (int)m_spiral.size(); ++m_updateTilesPos) {
|
||||
// avoid rendering too much tiles at once
|
||||
if((int)m_cachedVisibleTiles.size() > MAX_TILE_DRAWS) {
|
||||
stop = true;
|
||||
break;
|
||||
}
|
||||
|
||||
const Point& p = m_spiral[m_updateTilesPos];
|
||||
Position tilePos = cameraPosition.translated(p.x - m_virtualCenterOffset.x, p.y - m_virtualCenterOffset.y);
|
||||
tilePos.coveredUp(cameraPosition.z - iz);
|
||||
if(const TilePtr& tile = g_map.getTile(tilePos)) {
|
||||
if(tile->isDrawable())
|
||||
m_cachedVisibleTiles.push_back(tile);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!stop) {
|
||||
m_updateTilesPos = 0;
|
||||
m_spiral.clear();
|
||||
}
|
||||
|
||||
if(start == 0 && m_viewMode <= NEAR_VIEW)
|
||||
m_cachedFloorVisibleCreatures = g_map.getSpectators(cameraPosition, false);
|
||||
}
|
||||
|
||||
void MapView::updateGeometry(const Size& visibleDimension, const Size& optimizedSize)
|
||||
{
|
||||
int tileSize = 0;
|
||||
Size bufferSize;
|
||||
|
||||
if(!m_drawMinimapColors) {
|
||||
int possiblesTileSizes[] = {1,2,4,8,16,32};
|
||||
for(int candidateTileSize : possiblesTileSizes) {
|
||||
bufferSize = (visibleDimension + Size(3,3)) * candidateTileSize;
|
||||
if(bufferSize.width() > g_graphics.getMaxTextureSize() || bufferSize.height() > g_graphics.getMaxTextureSize())
|
||||
break;
|
||||
|
||||
tileSize = candidateTileSize;
|
||||
if(optimizedSize.width() < bufferSize.width() - 3*candidateTileSize && optimizedSize.height() < bufferSize.height() - 3*candidateTileSize)
|
||||
break;
|
||||
}
|
||||
|
||||
if(tileSize == 0) {
|
||||
g_logger.traceError("reached max zoom out");
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
tileSize = 1;
|
||||
bufferSize = visibleDimension + Size(3,3);
|
||||
}
|
||||
|
||||
Size drawDimension = visibleDimension + Size(3,3);
|
||||
Point virtualCenterOffset = (drawDimension/2 - Size(1,1)).toPoint();
|
||||
Point visibleCenterOffset = virtualCenterOffset;
|
||||
|
||||
ViewMode viewMode = m_viewMode;
|
||||
if(m_autoViewMode) {
|
||||
if(tileSize >= 32 && visibleDimension.area() <= NEAR_VIEW_AREA)
|
||||
viewMode = NEAR_VIEW;
|
||||
else if(tileSize >= 16 && visibleDimension.area() <= MID_VIEW_AREA)
|
||||
viewMode = MID_VIEW;
|
||||
else if(tileSize >= 8 && visibleDimension.area() <= FAR_VIEW_AREA)
|
||||
viewMode = FAR_VIEW;
|
||||
else
|
||||
viewMode = HUGE_VIEW;
|
||||
|
||||
if(viewMode >= FAR_VIEW)
|
||||
m_multifloor = false;
|
||||
else
|
||||
m_multifloor = true;
|
||||
}
|
||||
|
||||
// draw actually more than what is needed to avoid massive recalculations on huge views
|
||||
/*
|
||||
if(viewMode >= HUGE_VIEW) {
|
||||
Size oldDimension = drawDimension;
|
||||
drawDimension = (m_framebuffer->getSize() / tileSize);
|
||||
virtualCenterOffset += (drawDimension - oldDimension).toPoint() / 2;
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
m_viewMode = viewMode;
|
||||
m_visibleDimension = visibleDimension;
|
||||
m_drawDimension = drawDimension;
|
||||
m_tileSize = tileSize;
|
||||
m_virtualCenterOffset = virtualCenterOffset;
|
||||
m_visibleCenterOffset = visibleCenterOffset;
|
||||
m_optimizedSize = optimizedSize;
|
||||
m_framebuffer->resize(bufferSize);
|
||||
requestVisibleTilesCacheUpdate();
|
||||
}
|
||||
|
||||
void MapView::onTileUpdate(const Position& pos)
|
||||
{
|
||||
if(!m_drawMinimapColors)
|
||||
requestVisibleTilesCacheUpdate();
|
||||
}
|
||||
|
||||
void MapView::onMapCenterChange(const Position& pos)
|
||||
{
|
||||
requestVisibleTilesCacheUpdate();
|
||||
}
|
||||
|
||||
void MapView::lockFirstVisibleFloor(int firstVisibleFloor)
|
||||
{
|
||||
m_lockedFirstVisibleFloor = firstVisibleFloor;
|
||||
requestVisibleTilesCacheUpdate();
|
||||
}
|
||||
|
||||
void MapView::unlockFirstVisibleFloor()
|
||||
{
|
||||
m_lockedFirstVisibleFloor = -1;
|
||||
requestVisibleTilesCacheUpdate();
|
||||
}
|
||||
|
||||
void MapView::setVisibleDimension(const Size& visibleDimension)
|
||||
{
|
||||
if(visibleDimension == m_visibleDimension)
|
||||
return;
|
||||
|
||||
if(visibleDimension.width() % 2 != 1 || visibleDimension.height() % 2 != 1) {
|
||||
g_logger.traceError("visible dimension must be odd");
|
||||
return;
|
||||
}
|
||||
|
||||
if(visibleDimension < Size(3,3)) {
|
||||
g_logger.traceError("reach max zoom in");
|
||||
return;
|
||||
}
|
||||
|
||||
updateGeometry(visibleDimension, m_optimizedSize);
|
||||
}
|
||||
|
||||
void MapView::setViewMode(MapView::ViewMode viewMode)
|
||||
{
|
||||
m_viewMode = viewMode;
|
||||
requestVisibleTilesCacheUpdate();
|
||||
}
|
||||
|
||||
void MapView::setAutoViewMode(bool enable)
|
||||
{
|
||||
m_autoViewMode = enable;
|
||||
if(enable)
|
||||
updateGeometry(m_visibleDimension, m_optimizedSize);
|
||||
}
|
||||
|
||||
void MapView::optimizeForSize(const Size& visibleSize)
|
||||
{
|
||||
updateGeometry(m_visibleDimension, visibleSize);
|
||||
}
|
||||
|
||||
void MapView::followCreature(const CreaturePtr& creature)
|
||||
{
|
||||
m_follow = true;
|
||||
m_followingCreature = creature;
|
||||
requestVisibleTilesCacheUpdate();
|
||||
}
|
||||
|
||||
void MapView::setCameraPosition(const Position& pos)
|
||||
{
|
||||
m_follow = false;
|
||||
m_customCameraPosition = pos;
|
||||
requestVisibleTilesCacheUpdate();
|
||||
}
|
||||
|
||||
int MapView::calcFirstVisibleFloor()
|
||||
{
|
||||
int z = 7;
|
||||
// return forced first visible floor
|
||||
if(m_lockedFirstVisibleFloor != -1) {
|
||||
z = m_lockedFirstVisibleFloor;
|
||||
} else {
|
||||
Position cameraPosition = getCameraPosition();
|
||||
|
||||
// this could happens if the player is not known yet
|
||||
if(cameraPosition.isValid()) {
|
||||
// avoid rendering multifloors in far views
|
||||
if(!m_multifloor) {
|
||||
z = cameraPosition.z;
|
||||
} else {
|
||||
// if nothing is limiting the view, the first visible floor is 0
|
||||
int firstFloor = 0;
|
||||
|
||||
// limits to underground floors while under sea level
|
||||
if(cameraPosition.z > Otc::SEA_FLOOR)
|
||||
firstFloor = std::max(cameraPosition.z - Otc::AWARE_UNDEGROUND_FLOOR_RANGE, (int)Otc::UNDERGROUND_FLOOR);
|
||||
|
||||
// loop in 3x3 tiles around the camera
|
||||
for(int ix = -1; ix <= 1 && firstFloor < cameraPosition.z; ++ix) {
|
||||
for(int iy = -1; iy <= 1 && firstFloor < cameraPosition.z; ++iy) {
|
||||
Position pos = cameraPosition.translated(ix, iy);
|
||||
|
||||
// process tiles that we can look through, e.g. windows, doors
|
||||
if((ix == 0 && iy == 0) || (/*(std::abs(ix) != std::abs(iy)) && */g_map.isLookPossible(pos))) {
|
||||
Position upperPos = pos;
|
||||
Position coveredPos = pos;
|
||||
|
||||
while(coveredPos.coveredUp() && upperPos.up() && upperPos.z >= firstFloor) {
|
||||
// check tiles physically above
|
||||
TilePtr tile = g_map.getTile(upperPos);
|
||||
if(tile && tile->limitsFloorsView()) {
|
||||
firstFloor = upperPos.z + 1;
|
||||
break;
|
||||
}
|
||||
|
||||
// check tiles geometrically above
|
||||
tile = g_map.getTile(coveredPos);
|
||||
if(tile && tile->limitsFloorsView()) {
|
||||
firstFloor = coveredPos.z + 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
z = firstFloor;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// just ensure the that the floor is in the valid range
|
||||
z = std::min(std::max(z, 0), (int)Otc::MAX_Z);
|
||||
return z;
|
||||
}
|
||||
|
||||
int MapView::calcLastVisibleFloor()
|
||||
{
|
||||
if(!m_multifloor)
|
||||
return calcFirstVisibleFloor();
|
||||
|
||||
int z = 7;
|
||||
|
||||
Position cameraPosition = getCameraPosition();
|
||||
// this could happens if the player is not known yet
|
||||
if(cameraPosition.isValid()) {
|
||||
// view only underground floors when below sea level
|
||||
if(cameraPosition.z > Otc::SEA_FLOOR)
|
||||
z = cameraPosition.z + Otc::AWARE_UNDEGROUND_FLOOR_RANGE;
|
||||
else
|
||||
z = Otc::SEA_FLOOR;
|
||||
}
|
||||
|
||||
if(m_lockedFirstVisibleFloor != -1)
|
||||
z = std::max(m_lockedFirstVisibleFloor, z);
|
||||
|
||||
// just ensure the that the floor is in the valid range
|
||||
z = std::min(std::max(z, 0), (int)Otc::MAX_Z);
|
||||
return z;
|
||||
}
|
||||
|
||||
Position MapView::getCameraPosition()
|
||||
{
|
||||
if(isFollowingCreature())
|
||||
return m_followingCreature->getPosition();
|
||||
|
||||
return m_customCameraPosition;
|
||||
}
|
||||
|
||||
void MapView::setDrawMinimapColors(bool enable)
|
||||
{
|
||||
if(m_drawMinimapColors == enable)
|
||||
return;
|
||||
m_drawMinimapColors = enable;
|
||||
updateGeometry(m_visibleDimension, m_optimizedSize);
|
||||
requestVisibleTilesCacheUpdate();
|
||||
m_smooth = !enable;
|
||||
m_framebuffer->setSmooth(m_smooth);
|
||||
}
|
||||
|
||||
void MapView::setDrawLights(bool enable)
|
||||
{
|
||||
if(enable == m_drawLights)
|
||||
return;
|
||||
if(enable)
|
||||
m_lightView = LightViewPtr(new LightView);
|
||||
else
|
||||
m_lightView = nullptr;
|
||||
m_drawLights = enable;
|
||||
}
|
||||
158
src/client/mapview.h
Normal file
158
src/client/mapview.h
Normal file
@@ -0,0 +1,158 @@
|
||||
/*
|
||||
* Copyright (c) 2010-2013 OTClient <https://github.com/edubart/otclient>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef MAPVIEW_H
|
||||
#define MAPVIEW_H
|
||||
|
||||
#include "declarations.h"
|
||||
#include <framework/graphics/paintershaderprogram.h>
|
||||
#include <framework/graphics/declarations.h>
|
||||
#include <framework/luaengine/luaobject.h>
|
||||
#include <framework/core/declarations.h>
|
||||
|
||||
// @bindclass
|
||||
class MapView : public LuaObject
|
||||
{
|
||||
public:
|
||||
enum ViewMode {
|
||||
NEAR_VIEW,
|
||||
MID_VIEW,
|
||||
FAR_VIEW,
|
||||
HUGE_VIEW
|
||||
};
|
||||
|
||||
MapView();
|
||||
~MapView();
|
||||
void draw(const Rect& rect);
|
||||
|
||||
private:
|
||||
void updateGeometry(const Size& visibleDimension, const Size& optimizedSize);
|
||||
void updateVisibleTilesCache(int start = 0);
|
||||
void requestVisibleTilesCacheUpdate() { m_mustUpdateVisibleTilesCache = true; }
|
||||
|
||||
protected:
|
||||
void onTileUpdate(const Position& pos);
|
||||
void onMapCenterChange(const Position& pos);
|
||||
|
||||
friend class Map;
|
||||
|
||||
public:
|
||||
// floor visibility related
|
||||
void lockFirstVisibleFloor(int firstVisibleFloor);
|
||||
void unlockFirstVisibleFloor();
|
||||
int getLockedFirstVisibleFloor() { return m_lockedFirstVisibleFloor; }
|
||||
|
||||
void setMultifloor(bool enable) { m_multifloor = enable; requestVisibleTilesCacheUpdate(); }
|
||||
bool isMultifloor() { return m_multifloor; }
|
||||
|
||||
// map dimension related
|
||||
void setVisibleDimension(const Size& visibleDimension);
|
||||
Size getVisibleDimension() { return m_visibleDimension; }
|
||||
int getTileSize() { return m_tileSize; }
|
||||
Point getVisibleCenterOffset() { return m_visibleCenterOffset; }
|
||||
int getCachedFirstVisibleFloor() { return m_cachedFirstVisibleFloor; }
|
||||
int getCachedLastVisibleFloor() { return m_cachedLastVisibleFloor; }
|
||||
|
||||
// view mode related
|
||||
void setViewMode(ViewMode viewMode);
|
||||
ViewMode getViewMode() { return m_viewMode; }
|
||||
void optimizeForSize(const Size& visibleSize);
|
||||
|
||||
void setAutoViewMode(bool enable);
|
||||
bool isAutoViewModeEnabled() { return m_autoViewMode; }
|
||||
|
||||
// camera related
|
||||
void followCreature(const CreaturePtr& creature);
|
||||
CreaturePtr getFollowingCreature() { return m_followingCreature; }
|
||||
bool isFollowingCreature() { return m_followingCreature && m_follow; }
|
||||
|
||||
void setCameraPosition(const Position& pos);
|
||||
Position getCameraPosition();
|
||||
|
||||
void setMinimumAmbientLight(float intensity) { m_minimumAmbientLight = intensity; }
|
||||
float getMinimumAmbientLight() { return m_minimumAmbientLight; }
|
||||
|
||||
// drawing related
|
||||
void setDrawFlags(Otc::DrawFlags drawFlags) { m_drawFlags = drawFlags; requestVisibleTilesCacheUpdate(); }
|
||||
Otc::DrawFlags getDrawFlags() { return m_drawFlags; }
|
||||
|
||||
void setDrawTexts(bool enable) { m_drawTexts = enable; }
|
||||
bool isDrawingTexts() { return m_drawTexts; }
|
||||
|
||||
void setDrawMinimapColors(bool enable);
|
||||
bool isDrawingMinimapColors() { return m_drawMinimapColors; }
|
||||
|
||||
void setAnimated(bool animated) { m_animated = animated; requestVisibleTilesCacheUpdate(); }
|
||||
bool isAnimating() { return m_animated; }
|
||||
|
||||
void setDrawLights(bool enable);
|
||||
bool isDrawingLights() { return m_drawLights; }
|
||||
|
||||
void setShader(const PainterShaderProgramPtr& shader) { m_shader = shader; }
|
||||
PainterShaderProgramPtr getShader() { return m_shader; }
|
||||
|
||||
|
||||
MapViewPtr asMapView() { return static_self_cast<MapView>(); }
|
||||
|
||||
private:
|
||||
int calcFirstVisibleFloor();
|
||||
int calcLastVisibleFloor();
|
||||
Point transformPositionTo2D(const Position& position, const Position& relativePosition) {
|
||||
return Point((m_virtualCenterOffset.x + (position.x - relativePosition.x) - (relativePosition.z - position.z)) * m_tileSize,
|
||||
(m_virtualCenterOffset.y + (position.y - relativePosition.y) - (relativePosition.z - position.z)) * m_tileSize);
|
||||
}
|
||||
|
||||
int m_lockedFirstVisibleFloor;
|
||||
int m_cachedFirstVisibleFloor;
|
||||
int m_cachedLastVisibleFloor;
|
||||
int m_tileSize;
|
||||
int m_updateTilesPos;
|
||||
Size m_drawDimension;
|
||||
Size m_visibleDimension;
|
||||
Size m_optimizedSize;
|
||||
Point m_virtualCenterOffset;
|
||||
Point m_visibleCenterOffset;
|
||||
Position m_customCameraPosition;
|
||||
stdext::boolean<true> m_mustUpdateVisibleTilesCache;
|
||||
stdext::boolean<true> m_mustDrawVisibleTilesCache;
|
||||
stdext::boolean<true> m_mustCleanFramebuffer;
|
||||
stdext::boolean<true> m_multifloor;
|
||||
stdext::boolean<true> m_animated;
|
||||
stdext::boolean<true> m_autoViewMode;
|
||||
stdext::boolean<true> m_drawTexts;
|
||||
stdext::boolean<true> m_smooth;
|
||||
stdext::boolean<false> m_drawMinimapColors;
|
||||
stdext::boolean<false> m_drawLights;
|
||||
stdext::boolean<true> m_follow;
|
||||
std::vector<TilePtr> m_cachedVisibleTiles;
|
||||
std::vector<CreaturePtr> m_cachedFloorVisibleCreatures;
|
||||
CreaturePtr m_followingCreature;
|
||||
FrameBufferPtr m_framebuffer;
|
||||
PainterShaderProgramPtr m_shader;
|
||||
ViewMode m_viewMode;
|
||||
Otc::DrawFlags m_drawFlags;
|
||||
std::vector<Point> m_spiral;
|
||||
LightViewPtr m_lightView;
|
||||
float m_minimumAmbientLight;
|
||||
};
|
||||
|
||||
#endif
|
||||
25
src/client/minimap.cpp
Normal file
25
src/client/minimap.cpp
Normal file
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright (c) 2010-2013 OTClient <https://github.com/edubart/otclient>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
|
||||
#include "minimap.h"
|
||||
|
||||
66
src/client/minimap.h
Normal file
66
src/client/minimap.h
Normal file
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright (c) 2010-2013 OTClient <https://github.com/edubart/otclient>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef MINIMAP_H
|
||||
#define MINIMAP_H
|
||||
|
||||
#include "global.h"
|
||||
#include <framework/graphics/image.h>
|
||||
/*
|
||||
enum {
|
||||
MINIMAP_AREA_SIZE = 32
|
||||
};
|
||||
|
||||
struct MinimapArea
|
||||
{
|
||||
ImagePtr img;
|
||||
TexturePtr tex;
|
||||
uint8 colors[MINIMAP_AREA_SIZE][MINIMAP_AREA_SIZE];
|
||||
stdext::boolean<true> mustUpdate;
|
||||
};
|
||||
|
||||
class Minimap
|
||||
{
|
||||
|
||||
public:
|
||||
void init();
|
||||
void terminate();
|
||||
|
||||
void loadOtmm();
|
||||
void saveOtmm();
|
||||
|
||||
void updateTile(const Position& pos, uint8 color);
|
||||
|
||||
private:
|
||||
|
||||
struct MinimaAreaHasher : std::unary_function<Position, std::size_t> {
|
||||
std::size_t operator()(const Position& pos) const {
|
||||
return ((pos.x/MINIMAP_AREA_SIZE) * 0x8000 + (pos.y/MINIMAP_AREA_SIZE)) * 16 + pos.z;
|
||||
}
|
||||
};
|
||||
std::unordered_map<Position, ImagePtr, MinimaAreaHasher> m_areas;
|
||||
};
|
||||
|
||||
extern Minimap g_minimap;
|
||||
*/
|
||||
#endif
|
||||
99
src/client/missile.cpp
Normal file
99
src/client/missile.cpp
Normal file
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
* Copyright (c) 2010-2013 OTClient <https://github.com/edubart/otclient>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "missile.h"
|
||||
#include "thingtypemanager.h"
|
||||
#include "map.h"
|
||||
#include "tile.h"
|
||||
#include <framework/core/clock.h>
|
||||
#include <framework/core/eventdispatcher.h>
|
||||
|
||||
void Missile::draw(const Point& dest, float scaleFactor, bool animate, LightView *lightView)
|
||||
{
|
||||
if(m_id == 0 || !animate)
|
||||
return;
|
||||
|
||||
int xPattern = 0, yPattern = 0;
|
||||
if(m_direction == Otc::NorthWest) {
|
||||
xPattern = 0;
|
||||
yPattern = 0;
|
||||
} else if(m_direction == Otc::North) {
|
||||
xPattern = 1;
|
||||
yPattern = 0;
|
||||
} else if(m_direction == Otc::NorthEast) {
|
||||
xPattern = 2;
|
||||
yPattern = 0;
|
||||
} else if(m_direction == Otc::East) {
|
||||
xPattern = 2;
|
||||
yPattern = 1;
|
||||
} else if(m_direction == Otc::SouthEast) {
|
||||
xPattern = 2;
|
||||
yPattern = 2;
|
||||
} else if(m_direction == Otc::South) {
|
||||
xPattern = 1;
|
||||
yPattern = 2;
|
||||
} else if(m_direction == Otc::SouthWest) {
|
||||
xPattern = 0;
|
||||
yPattern = 2;
|
||||
} else if(m_direction == Otc::West) {
|
||||
xPattern = 0;
|
||||
yPattern = 1;
|
||||
} else {
|
||||
xPattern = 1;
|
||||
yPattern = 1;
|
||||
}
|
||||
|
||||
float fraction = m_animationTimer.ticksElapsed() / m_duration;
|
||||
rawGetThingType()->draw(dest + m_delta * fraction * scaleFactor, scaleFactor, 0, xPattern, yPattern, 0, 0, lightView);
|
||||
}
|
||||
|
||||
void Missile::setPath(const Position& fromPosition, const Position& toPosition)
|
||||
{
|
||||
m_direction = fromPosition.getDirectionFromPosition(toPosition);
|
||||
|
||||
m_position = fromPosition;
|
||||
m_delta = Point(toPosition.x - fromPosition.x, toPosition.y - fromPosition.y);
|
||||
m_duration = 150 * std::sqrt(m_delta.length());
|
||||
m_delta *= Otc::TILE_PIXELS;
|
||||
m_animationTimer.restart();
|
||||
|
||||
// schedule removal
|
||||
auto self = asMissile();
|
||||
g_dispatcher.scheduleEvent([self]() { g_map.removeThing(self); }, m_duration);
|
||||
}
|
||||
|
||||
void Missile::setId(uint32 id)
|
||||
{
|
||||
if(!g_things.isValidDatId(id, ThingCategoryMissile))
|
||||
id = 0;
|
||||
m_id = id;
|
||||
}
|
||||
|
||||
const ThingTypePtr& Missile::getThingType()
|
||||
{
|
||||
return g_things.getThingType(m_id, ThingCategoryMissile);
|
||||
}
|
||||
|
||||
ThingType* Missile::rawGetThingType()
|
||||
{
|
||||
return g_things.rawGetThingType(m_id, ThingCategoryMissile);
|
||||
}
|
||||
59
src/client/missile.h
Normal file
59
src/client/missile.h
Normal file
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright (c) 2010-2013 OTClient <https://github.com/edubart/otclient>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef SHOT_H
|
||||
#define SHOT_H
|
||||
|
||||
#include <framework/global.h>
|
||||
#include <framework/core/timer.h>
|
||||
#include "thing.h"
|
||||
|
||||
// @bindclass
|
||||
class Missile : public Thing
|
||||
{
|
||||
enum {
|
||||
TICKS_PER_FRAME = 75
|
||||
};
|
||||
|
||||
public:
|
||||
void draw(const Point& dest, float scaleFactor, bool animate, LightView *lightView = nullptr);
|
||||
|
||||
void setId(uint32 id);
|
||||
void setPath(const Position& fromPosition, const Position& toPosition);
|
||||
|
||||
uint32 getId() { return m_id; }
|
||||
|
||||
MissilePtr asMissile() { return static_self_cast<Missile>(); }
|
||||
bool isMissile() { return true; }
|
||||
|
||||
const ThingTypePtr& getThingType();
|
||||
ThingType *rawGetThingType();
|
||||
|
||||
private:
|
||||
Timer m_animationTimer;
|
||||
Point m_delta;
|
||||
float m_duration;
|
||||
uint16 m_id;
|
||||
Otc::Direction m_direction;
|
||||
};
|
||||
|
||||
#endif
|
||||
131
src/client/outfit.cpp
Normal file
131
src/client/outfit.cpp
Normal file
@@ -0,0 +1,131 @@
|
||||
/*
|
||||
* Copyright (c) 2010-2013 OTClient <https://github.com/edubart/otclient>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "outfit.h"
|
||||
|
||||
Outfit::Outfit()
|
||||
{
|
||||
m_category = ThingCategoryCreature;
|
||||
m_id = 128;
|
||||
m_auxId = 0;
|
||||
resetClothes();
|
||||
}
|
||||
|
||||
Color Outfit::getColor(int color)
|
||||
{
|
||||
if(color >= HSI_H_STEPS * HSI_SI_VALUES)
|
||||
color = 0;
|
||||
|
||||
float loc1 = 0, loc2 = 0, loc3 = 0;
|
||||
if(color % HSI_H_STEPS != 0) {
|
||||
loc1 = color % HSI_H_STEPS * 1.0/18.0;
|
||||
loc2 = 1;
|
||||
loc3 = 1;
|
||||
|
||||
switch(int(color / HSI_H_STEPS)) {
|
||||
case 0:
|
||||
loc2 = 0.25;
|
||||
loc3 = 1.00;
|
||||
break;
|
||||
case 1:
|
||||
loc2 = 0.25;
|
||||
loc3 = 0.75;
|
||||
break;
|
||||
case 2:
|
||||
loc2 = 0.50;
|
||||
loc3 = 0.75;
|
||||
break;
|
||||
case 3:
|
||||
loc2 = 0.667;
|
||||
loc3 = 0.75;
|
||||
break;
|
||||
case 4:
|
||||
loc2 = 1.00;
|
||||
loc3 = 1.00;
|
||||
break;
|
||||
case 5:
|
||||
loc2 = 1.00;
|
||||
loc3 = 0.75;
|
||||
break;
|
||||
case 6:
|
||||
loc2 = 1.00;
|
||||
loc3 = 0.50;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
loc1 = 0;
|
||||
loc2 = 0;
|
||||
loc3 = 1 - (float)color / HSI_H_STEPS / (float)HSI_SI_VALUES;
|
||||
}
|
||||
|
||||
if(loc3 == 0)
|
||||
return Color(0, 0, 0);
|
||||
|
||||
if(loc2 == 0) {
|
||||
int loc7 = int(loc3 * 255);
|
||||
return Color(loc7, loc7, loc7);
|
||||
}
|
||||
|
||||
float red = 0, green = 0, blue = 0;
|
||||
|
||||
if(loc1 < 1.0/6.0) {
|
||||
red = loc3;
|
||||
blue = loc3 * (1 - loc2);
|
||||
green = blue + (loc3 - blue) * 6 * loc1;
|
||||
}
|
||||
else if(loc1 < 2.0/6.0) {
|
||||
green = loc3;
|
||||
blue = loc3 * (1 - loc2);
|
||||
red = green - (loc3 - blue) * (6 * loc1 - 1);
|
||||
}
|
||||
else if(loc1 < 3.0/6.0) {
|
||||
green = loc3;
|
||||
red = loc3 * (1 - loc2);
|
||||
blue = red + (loc3 - red) * (6 * loc1 - 2);
|
||||
}
|
||||
else if(loc1 < 4.0/6.0) {
|
||||
blue = loc3;
|
||||
red = loc3 * (1 - loc2);
|
||||
green = blue - (loc3 - red) * (6 * loc1 - 3);
|
||||
}
|
||||
else if(loc1 < 5.0/6.0) {
|
||||
blue = loc3;
|
||||
green = loc3 * (1 - loc2);
|
||||
red = green + (loc3 - green) * (6 * loc1 - 4);
|
||||
}
|
||||
else {
|
||||
red = loc3;
|
||||
green = loc3 * (1 - loc2);
|
||||
blue = red - (loc3 - green) * (6 * loc1 - 5);
|
||||
}
|
||||
return Color(int(red * 255), int(green * 255), int(blue * 255));
|
||||
}
|
||||
|
||||
void Outfit::resetClothes()
|
||||
{
|
||||
setHead(0);
|
||||
setBody(0);
|
||||
setLegs(0);
|
||||
setFeet(0);
|
||||
setMount(0);
|
||||
}
|
||||
74
src/client/outfit.h
Normal file
74
src/client/outfit.h
Normal file
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright (c) 2010-2013 OTClient <https://github.com/edubart/otclient>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef OUTFIT_H
|
||||
#define OUTFIT_H
|
||||
|
||||
#include <framework/util/color.h>
|
||||
#include "thingtypemanager.h"
|
||||
|
||||
class Outfit
|
||||
{
|
||||
enum {
|
||||
HSI_SI_VALUES = 7,
|
||||
HSI_H_STEPS = 19
|
||||
};
|
||||
|
||||
public:
|
||||
Outfit();
|
||||
|
||||
static Color getColor(int color);
|
||||
|
||||
void setId(int id) { m_id = id; }
|
||||
void setAuxId(int id) { m_auxId = id; }
|
||||
void setHead(int head) { m_head = head; m_headColor = getColor(head); }
|
||||
void setBody(int body) { m_body = body; m_bodyColor = getColor(body); }
|
||||
void setLegs(int legs) { m_legs = legs; m_legsColor = getColor(legs); }
|
||||
void setFeet(int feet) { m_feet = feet; m_feetColor = getColor(feet); }
|
||||
void setAddons(int addons) { m_addons = addons; }
|
||||
void setMount(int mount) { m_mount = mount; }
|
||||
void setCategory(ThingCategory category) { m_category = category; }
|
||||
|
||||
void resetClothes();
|
||||
|
||||
int getId() const { return m_id; }
|
||||
int getAuxId() const { return m_auxId; }
|
||||
int getHead() const { return m_head; }
|
||||
int getBody() const { return m_body; }
|
||||
int getLegs() const { return m_legs; }
|
||||
int getFeet() const { return m_feet; }
|
||||
int getAddons() const { return m_addons; }
|
||||
int getMount() const { return m_mount; }
|
||||
ThingCategory getCategory() const { return m_category; }
|
||||
|
||||
Color getHeadColor() const { return m_headColor; }
|
||||
Color getBodyColor() const { return m_bodyColor; }
|
||||
Color getLegsColor() const { return m_legsColor; }
|
||||
Color getFeetColor() const { return m_feetColor; }
|
||||
|
||||
private:
|
||||
ThingCategory m_category;
|
||||
int m_id, m_auxId, m_head, m_body, m_legs, m_feet, m_addons, m_mount;
|
||||
Color m_headColor, m_bodyColor, m_legsColor, m_feetColor;
|
||||
};
|
||||
|
||||
#endif
|
||||
23
src/client/player.cpp
Normal file
23
src/client/player.cpp
Normal file
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright (c) 2010-2013 OTClient <https://github.com/edubart/otclient>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "player.h"
|
||||
39
src/client/player.h
Normal file
39
src/client/player.h
Normal file
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (c) 2010-2013 OTClient <https://github.com/edubart/otclient>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef PLAYER_H
|
||||
#define PLAYER_H
|
||||
|
||||
#include "creature.h"
|
||||
|
||||
// @bindclass
|
||||
class Player : public Creature
|
||||
{
|
||||
public:
|
||||
Player() { }
|
||||
virtual ~Player() { }
|
||||
|
||||
PlayerPtr asPlayer() { return static_self_cast<Player>(); }
|
||||
bool isPlayer() { return true; }
|
||||
};
|
||||
|
||||
#endif
|
||||
241
src/client/position.h
Normal file
241
src/client/position.h
Normal file
@@ -0,0 +1,241 @@
|
||||
/*
|
||||
* Copyright (c) 2010-2013 OTClient <https://github.com/edubart/otclient>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef POSITION_H
|
||||
#define POSITION_H
|
||||
|
||||
#include "const.h"
|
||||
#include <framework/stdext/types.h>
|
||||
#include <framework/const.h>
|
||||
#include <framework/util/point.h>
|
||||
|
||||
class Position
|
||||
{
|
||||
public:
|
||||
Position() : x(65535), y(65535), z(255) { }
|
||||
Position(uint16 x, uint16 y, uint8 z) : x(x), y(y), z(z) { }
|
||||
|
||||
Position translatedToDirection(Otc::Direction direction) {
|
||||
Position pos = *this;
|
||||
switch(direction) {
|
||||
case Otc::North:
|
||||
pos.y--;
|
||||
break;
|
||||
case Otc::East:
|
||||
pos.x++;
|
||||
break;
|
||||
case Otc::South:
|
||||
pos.y++;
|
||||
break;
|
||||
case Otc::West:
|
||||
pos.x--;
|
||||
break;
|
||||
case Otc::NorthEast:
|
||||
pos.x++;
|
||||
pos.y--;
|
||||
break;
|
||||
case Otc::SouthEast:
|
||||
pos.x++;
|
||||
pos.y++;
|
||||
break;
|
||||
case Otc::SouthWest:
|
||||
pos.x--;
|
||||
pos.y++;
|
||||
break;
|
||||
case Otc::NorthWest:
|
||||
pos.x--;
|
||||
pos.y--;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return pos;
|
||||
}
|
||||
|
||||
Position translatedToReverseDirection(Otc::Direction direction) {
|
||||
Position pos = *this;
|
||||
switch(direction) {
|
||||
case Otc::North:
|
||||
pos.y++;
|
||||
break;
|
||||
case Otc::East:
|
||||
pos.x--;
|
||||
break;
|
||||
case Otc::South:
|
||||
pos.y--;
|
||||
break;
|
||||
case Otc::West:
|
||||
pos.x++;
|
||||
break;
|
||||
case Otc::NorthEast:
|
||||
pos.x--;
|
||||
pos.y++;
|
||||
break;
|
||||
case Otc::SouthEast:
|
||||
pos.x--;
|
||||
pos.y--;
|
||||
break;
|
||||
case Otc::SouthWest:
|
||||
pos.x++;
|
||||
pos.y--;
|
||||
break;
|
||||
case Otc::NorthWest:
|
||||
pos.x++;
|
||||
pos.y++;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return pos;
|
||||
}
|
||||
|
||||
Otc::Direction getDirectionFromPosition(const Position& position) const {
|
||||
int dx = position.x - x;
|
||||
int dy = position.y - y;
|
||||
|
||||
if(dx == 0 && dy == 0)
|
||||
return Otc::InvalidDirection;
|
||||
else if(dx == 0) {
|
||||
if(dy < 0)
|
||||
return Otc::North;
|
||||
else if(dy > 0)
|
||||
return Otc::South;
|
||||
}
|
||||
else if(dy == 0) {
|
||||
if(dx < 0)
|
||||
return Otc::West;
|
||||
else if(dx > 0)
|
||||
return Otc::East;
|
||||
}
|
||||
else {
|
||||
float angle = std::atan2(dy * -1, dx) * RAD_TO_DEC;
|
||||
if(angle < 0)
|
||||
angle += 360;
|
||||
|
||||
if(angle >= 360 - 22.5 || angle < 0 + 22.5)
|
||||
return Otc::East;
|
||||
else if(angle >= 45 - 22.5 && angle < 45 + 22.5)
|
||||
return Otc::NorthEast;
|
||||
else if(angle >= 90 - 22.5 && angle < 90 + 22.5)
|
||||
return Otc::North;
|
||||
else if(angle >= 135 - 22.5 && angle < 135 + 22.5)
|
||||
return Otc::NorthWest;
|
||||
else if(angle >= 180 - 22.5 && angle < 180 + 22.5)
|
||||
return Otc::West;
|
||||
else if(angle >= 225 - 22.5 && angle < 225 + 22.5)
|
||||
return Otc::SouthWest;
|
||||
else if(angle >= 270 - 22.5 && angle < 270 + 22.5)
|
||||
return Otc::South;
|
||||
else if(angle >= 315 - 22.5 && angle < 315 + 22.5)
|
||||
return Otc::SouthEast;
|
||||
}
|
||||
return Otc::InvalidDirection;
|
||||
}
|
||||
|
||||
bool isMapPosition() const { return (x < 65535 && y < 65535 && z <= Otc::MAX_Z); }
|
||||
bool isValid() const { return !(x == 65535 && y == 65535 && z == 255); }
|
||||
float distance(const Position& pos) const { return sqrt(pow((pos.x - x), 2) + pow((pos.y - y), 2)); }
|
||||
int manhattanDistance(const Position& pos) const { return std::abs(pos.x - x) + std::abs(pos.y - y); }
|
||||
|
||||
void translate(int dx, int dy, short dz = 0) { x += dx; y += dy; z += dz; }
|
||||
Position translated(int dx, int dy, short dz = 0) const { Position pos = *this; pos.x += dx; pos.y += dy; pos.z += dz; return pos; }
|
||||
|
||||
Position operator+(const Position& other) const { return Position(x + other.x, y + other.y, z + other.z); }
|
||||
Position& operator+=(const Position& other) { x+=other.x; y+=other.y; z +=other.z; return *this; }
|
||||
Position operator-(const Position& other) const { return Position(x - other.x, y - other.y, z - other.z); }
|
||||
Position& operator-=(const Position& other) { x-=other.x; y-=other.y; z-=other.z; return *this; }
|
||||
// Point conversion(s)
|
||||
Position operator+(const Point& other) const { return Position(x + other.x, y + other.y, z); }
|
||||
Position& operator+=(const Point& other) { x += other.x; y += other.y; return *this; }
|
||||
|
||||
Position& operator=(const Position& other) { x = other.x; y = other.y; z = other.z; return *this; }
|
||||
bool operator==(const Position& other) const { return other.x == x && other.y == y && other.z == z; }
|
||||
bool operator!=(const Position& other) const { return other.x!=x || other.y!=y || other.z!=z; }
|
||||
bool isInRange(const Position& pos, int xRange, int yRange) const { return std::abs(x-pos.x) <= xRange && std::abs(y-pos.y) <= yRange && z == pos.z; }
|
||||
bool isInRange(const Position& pos, int minXRange, int maxXRange, int minYRange, int maxYRange) const {
|
||||
return (pos.x >= x-minXRange && pos.x <= x+maxXRange && pos.y >= y-minYRange && pos.y <= y+maxYRange && pos.z == z);
|
||||
}
|
||||
|
||||
bool up(int n = 1) {
|
||||
int nz = z-n;
|
||||
if(nz >= 0 && nz <= Otc::MAX_Z) {
|
||||
z = nz;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool down(int n = 1) {
|
||||
int nz = z+n;
|
||||
if(nz >= 0 && nz <= Otc::MAX_Z) {
|
||||
z = nz;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool coveredUp(int n = 1) {
|
||||
int nx = x+n, ny = y+n, nz = z-n;
|
||||
if(nx >= 0 && nx <= 65535 && ny >= 0 && ny <= 65535 && nz >= 0 && nz <= Otc::MAX_Z) {
|
||||
x = nx; y = ny; z = nz;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool coveredDown(int n = 1) {
|
||||
int nx = x-n, ny = y-n, nz = z+n;
|
||||
if(nx >= 0 && nx <= 65535 && ny >= 0 && ny <= 65535 && nz >= 0 && nz <= Otc::MAX_Z) {
|
||||
x = nx; y = ny; z = nz;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
uint16 x;
|
||||
uint16 y;
|
||||
uint8 z;
|
||||
};
|
||||
|
||||
struct PositionHasher : std::unary_function<Position, std::size_t> {
|
||||
std::size_t operator()(const Position& pos) const {
|
||||
return (((pos.x * 8192) + pos.y) * 16) + pos.z;
|
||||
}
|
||||
};
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& out, const Position& pos)
|
||||
{
|
||||
out << (int)pos.x << " " << (int)pos.y << " " << (int)pos.z;
|
||||
return out;
|
||||
}
|
||||
|
||||
inline std::istream& operator>>(std::istream& in, Position& pos)
|
||||
{
|
||||
int x, y, z;
|
||||
in >> x >> y >> z;
|
||||
pos.x = x;
|
||||
pos.y = y;
|
||||
pos.z = z;
|
||||
return in;
|
||||
}
|
||||
|
||||
#endif
|
||||
138
src/client/protocolcodes.cpp
Normal file
138
src/client/protocolcodes.cpp
Normal file
@@ -0,0 +1,138 @@
|
||||
/*
|
||||
* Copyright (c) 2010-2013 OTClient <https://github.com/edubart/otclient>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "protocolcodes.h"
|
||||
|
||||
namespace Proto {
|
||||
|
||||
std::map<uint8, uint8> messageModesMap;
|
||||
|
||||
void buildMessageModesMap(int version) {
|
||||
messageModesMap.clear();
|
||||
if(version >= 900) {
|
||||
for(int i=Otc::MessageNone;i<=Otc::MessageBeyondLast;++i)
|
||||
messageModesMap[i] = i;
|
||||
} else if(version >= 861) {
|
||||
messageModesMap[Otc::MessageNone] = 0;
|
||||
messageModesMap[Otc::MessageSay] = 1;
|
||||
messageModesMap[Otc::MessageWhisper] = 2;
|
||||
messageModesMap[Otc::MessageYell] = 3;
|
||||
messageModesMap[Otc::MessageNpcTo] = 4;
|
||||
messageModesMap[Otc::MessageNpcFrom] = 5;
|
||||
messageModesMap[Otc::MessagePrivateFrom] = 6;
|
||||
messageModesMap[Otc::MessagePrivateTo] = 6;
|
||||
messageModesMap[Otc::MessageChannel] = 7;
|
||||
messageModesMap[Otc::MessageChannelManagement] = 8;
|
||||
messageModesMap[Otc::MessageGamemasterBroadcast] = 9;
|
||||
messageModesMap[Otc::MessageGamemasterChannel] = 10;
|
||||
messageModesMap[Otc::MessageGamemasterPrivateFrom] = 11;
|
||||
messageModesMap[Otc::MessageGamemasterPrivateTo] = 11;
|
||||
messageModesMap[Otc::MessageChannelHighlight] = 12;
|
||||
messageModesMap[Otc::MessageMonsterSay] = 13;
|
||||
messageModesMap[Otc::MessageMonsterYell] = 14;
|
||||
messageModesMap[Otc::MessageWarning] = 15;
|
||||
messageModesMap[Otc::MessageGame] = 16;
|
||||
messageModesMap[Otc::MessageLogin] = 17;
|
||||
messageModesMap[Otc::MessageStatus] = 18;
|
||||
messageModesMap[Otc::MessageLook] = 19;
|
||||
messageModesMap[Otc::MessageFailure] = 20;
|
||||
messageModesMap[Otc::MessageBlue] = 21;
|
||||
messageModesMap[Otc::MessageRed] = 22;
|
||||
} else if(version >= 854) {
|
||||
messageModesMap[Otc::MessageNone] = 0;
|
||||
messageModesMap[Otc::MessageSay] = 1;
|
||||
messageModesMap[Otc::MessageWhisper] = 2;
|
||||
messageModesMap[Otc::MessageYell] = 3;
|
||||
messageModesMap[Otc::MessageNpcTo] = 4;
|
||||
messageModesMap[Otc::MessageNpcFrom] = 5;
|
||||
messageModesMap[Otc::MessagePrivateFrom] = 6;
|
||||
messageModesMap[Otc::MessagePrivateTo] = 6;
|
||||
messageModesMap[Otc::MessageChannel] = 7;
|
||||
messageModesMap[Otc::MessageChannelManagement] = 8;
|
||||
messageModesMap[Otc::MessageRVRChannel] = 9;
|
||||
messageModesMap[Otc::MessageRVRAnswer] = 10;
|
||||
messageModesMap[Otc::MessageRVRContinue] = 11;
|
||||
messageModesMap[Otc::MessageGamemasterBroadcast] = 12;
|
||||
messageModesMap[Otc::MessageGamemasterChannel] = 13;
|
||||
messageModesMap[Otc::MessageGamemasterPrivateFrom] = 14;
|
||||
messageModesMap[Otc::MessageGamemasterPrivateTo] = 14;
|
||||
messageModesMap[Otc::MessageChannelHighlight] = 15;
|
||||
// 16, 17, 18 ??
|
||||
messageModesMap[Otc::MessageRed] = 18;
|
||||
messageModesMap[Otc::MessageMonsterSay] = 19;
|
||||
messageModesMap[Otc::MessageMonsterYell] = 20;
|
||||
messageModesMap[Otc::MessageWarning] = 21;
|
||||
messageModesMap[Otc::MessageGame] = 22;
|
||||
messageModesMap[Otc::MessageLogin] = 23;
|
||||
messageModesMap[Otc::MessageStatus] = 24;
|
||||
messageModesMap[Otc::MessageLook] = 25;
|
||||
messageModesMap[Otc::MessageFailure] = 26;
|
||||
messageModesMap[Otc::MessageBlue] = 27;
|
||||
} else if(version >= 810) {
|
||||
messageModesMap[Otc::MessageNone] = 0;
|
||||
messageModesMap[Otc::MessageSay] = 1;
|
||||
messageModesMap[Otc::MessageWhisper] = 2;
|
||||
messageModesMap[Otc::MessageYell] = 3;
|
||||
messageModesMap[Otc::MessagePrivateFrom] = 4;
|
||||
messageModesMap[Otc::MessagePrivateTo] = 4;
|
||||
messageModesMap[Otc::MessageChannel] = 5;
|
||||
messageModesMap[Otc::MessageRVRChannel] = 6;
|
||||
messageModesMap[Otc::MessageRVRAnswer] = 7;
|
||||
messageModesMap[Otc::MessageRVRContinue] = 8;
|
||||
messageModesMap[Otc::MessageGamemasterBroadcast] = 9;
|
||||
messageModesMap[Otc::MessageGamemasterChannel] = 10;
|
||||
messageModesMap[Otc::MessageGamemasterPrivateFrom] = 11;
|
||||
messageModesMap[Otc::MessageGamemasterPrivateTo] = 11;
|
||||
messageModesMap[Otc::MessageChannelHighlight] = 12;
|
||||
// 13, 14, 15 ??
|
||||
messageModesMap[Otc::MessageMonsterSay] = 16;
|
||||
messageModesMap[Otc::MessageMonsterYell] = 17;
|
||||
messageModesMap[Otc::MessageWarning] = 18;
|
||||
messageModesMap[Otc::MessageGame] = 19;
|
||||
messageModesMap[Otc::MessageLogin] = 20;
|
||||
messageModesMap[Otc::MessageStatus] = 21;
|
||||
messageModesMap[Otc::MessageLook] = 22;
|
||||
messageModesMap[Otc::MessageFailure] = 23;
|
||||
messageModesMap[Otc::MessageBlue] = 24;
|
||||
messageModesMap[Otc::MessageRed] = 25;
|
||||
}
|
||||
}
|
||||
|
||||
Otc::MessageMode translateMessageModeFromServer(uint8 mode)
|
||||
{
|
||||
auto it = std::find_if(messageModesMap.begin(), messageModesMap.end(), [=] (const std::pair<uint8, uint8>& p) { return p.second == mode; });
|
||||
if(it != messageModesMap.end())
|
||||
return (Otc::MessageMode)it->first;
|
||||
return Otc::MessageInvalid;
|
||||
}
|
||||
|
||||
uint8 translateMessageModeToServer(Otc::MessageMode mode)
|
||||
{
|
||||
if(mode < 0 || mode >= Otc::LastMessage)
|
||||
return Otc::MessageInvalid;
|
||||
auto it = messageModesMap.find(mode);
|
||||
if(it != messageModesMap.end())
|
||||
return it->second;
|
||||
return Otc::MessageInvalid;
|
||||
}
|
||||
|
||||
}
|
||||
260
src/client/protocolcodes.h
Normal file
260
src/client/protocolcodes.h
Normal file
@@ -0,0 +1,260 @@
|
||||
/*
|
||||
* Copyright (c) 2010-2013 OTClient <https://github.com/edubart/otclient>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef PROTOCOLCODES_H
|
||||
#define PROTOCOLCODES_H
|
||||
|
||||
#include "global.h"
|
||||
|
||||
namespace Proto {
|
||||
enum LoginServerOpts {
|
||||
LoginServerError = 10,
|
||||
LoginServerMotd = 20,
|
||||
LoginServerUpdateNeeded = 30,
|
||||
LoginServerCharacterList = 100
|
||||
};
|
||||
|
||||
enum CreatureOpcode {
|
||||
UnknownCreature = 97,
|
||||
OutdatedCreature = 98,
|
||||
Creature = 99
|
||||
};
|
||||
|
||||
enum GameServerOpcodes : uint8
|
||||
{
|
||||
GameServerInitGame = 10,
|
||||
GameServerGMActions = 11,
|
||||
GameServerEnterGame = 15,
|
||||
GameServerLoginError = 20,
|
||||
GameServerLoginAdvice = 21,
|
||||
GameServerLoginWait = 22,
|
||||
GameServerAddCreature = 23,
|
||||
GameServerPingBack = 29,
|
||||
GameServerPing = 30,
|
||||
GameServerChallange = 31,
|
||||
GameServerDeath = 40,
|
||||
|
||||
// all in game opcodes must be greater than 50
|
||||
GameServerFirstGameOpcode = 50,
|
||||
|
||||
// otclient ONLY
|
||||
GameServerExtendedOpcode = 50,
|
||||
|
||||
// NOTE: add any custom opcodes in this range
|
||||
// 51 - 99
|
||||
|
||||
// original tibia ONLY
|
||||
GameServerFullMap = 100,
|
||||
GameServerMapTopRow = 101,
|
||||
GameServerMapRightRow = 102,
|
||||
GameServerMapBottomRow = 103,
|
||||
GameServerMapLeftRow = 104,
|
||||
GameServerUpdateTile = 105,
|
||||
GameServerCreateOnMap = 106,
|
||||
GameServerChangeOnMap = 107,
|
||||
GameServerDeleteOnMap = 108,
|
||||
GameServerMoveCreature = 109,
|
||||
GameServerOpenContainer = 110,
|
||||
GameServerCloseContainer = 111,
|
||||
GameServerCreateContainer = 112,
|
||||
GameServerChangeInContainer = 113,
|
||||
GameServerDeleteInContainer = 114,
|
||||
GameServerSetInventory = 120,
|
||||
GameServerDeleteInventory = 121,
|
||||
GameServerOpenNpcTrade = 122,
|
||||
GameServerPlayerGoods = 123,
|
||||
GameServerCloseNpcTrade = 124,
|
||||
GameServerOwnTrade = 125,
|
||||
GameServerCounterTrade = 126,
|
||||
GameServerCloseTrade = 127,
|
||||
GameServerAmbient = 130,
|
||||
GameServerGraphicalEffect = 131,
|
||||
GameServerTextEffect = 132,
|
||||
GameServerMissleEffect = 133,
|
||||
GameServerMarkCreature = 134,
|
||||
GameServerTrappers = 135,
|
||||
GameServerCreatureHealth = 140,
|
||||
GameServerCreatureLight = 141,
|
||||
GameServerCreatureOutfit = 142,
|
||||
GameServerCreatureSpeed = 143,
|
||||
GameServerCreatureSkull = 144,
|
||||
GameServerCreatureParty = 145,
|
||||
GameServerCreatureUnpass = 146,
|
||||
GameServerEditText = 150,
|
||||
GameServerEditList = 151,
|
||||
GameServerPlayerDataBasic = 159, // 950
|
||||
GameServerPlayerData = 160,
|
||||
GameServerPlayerSkills = 161,
|
||||
GameServerPlayerState = 162,
|
||||
GameServerClearTarget = 163,
|
||||
GameServerSpellDelay = 164, // 870
|
||||
GameServerSpellGroupDelay = 165, // 870
|
||||
GameServerMultiUseDelay = 166, // 870
|
||||
GameServerTalk = 170,
|
||||
GameServerChannels = 171,
|
||||
GameServerOpenChannel = 172,
|
||||
GameServerOpenPrivateChannel = 173,
|
||||
GameServerRuleViolationChannel = 174,
|
||||
GameServerRuleViolationRemove = 175,
|
||||
GameServerRuleViolationCancel = 176,
|
||||
GameServerRuleViolationLock = 177,
|
||||
GameServerOpenOwnChannel = 178,
|
||||
GameServerCloseChannel = 179,
|
||||
GameServerTextMessage = 180,
|
||||
GameServerCancelWalk = 181,
|
||||
GameServerWalkWait = 182,
|
||||
GameServerFloorChangeUp = 190,
|
||||
GameServerFloorChangeDown = 191,
|
||||
GameServerChooseOutfit = 200,
|
||||
GameServerVipAdd = 210,
|
||||
GameServerVipState = 211,
|
||||
GameServerVipLogout = 212,
|
||||
GameServerTutorialHint = 220,
|
||||
GameServerAutomapFlag = 221,
|
||||
GameServerQuestLog = 240,
|
||||
GameServerQuestLine = 241,
|
||||
GameServerChannelEvent = 243, // 910
|
||||
GameServerItemInfo = 244, // 910
|
||||
GameServerPlayerInventory = 245, // 910
|
||||
GameServerMarketEnter = 246, // 944
|
||||
GameServerMarketLeave = 247, // 944
|
||||
GameServerMarketDetail = 248, // 944
|
||||
GameServerMarketBrowse = 249, // 944
|
||||
GameServerShowModalDialog = 250 // 960
|
||||
};
|
||||
|
||||
enum ClientOpcodes : uint8
|
||||
{
|
||||
ClientEnterAccount = 1,
|
||||
ClientPendingGame = 10,
|
||||
ClientEnterGame = 15,
|
||||
ClientLeaveGame = 20,
|
||||
ClientPing = 29,
|
||||
ClientPingBack = 30,
|
||||
|
||||
// all in game opcodes must be equal or greater than 50
|
||||
ClientFirstGameOpcode = 50,
|
||||
|
||||
// otclient ONLY
|
||||
ClientExtendedOpcode = 50,
|
||||
|
||||
// NOTE: add any custom opcodes in this range
|
||||
// 51 - 99
|
||||
|
||||
// original tibia ONLY
|
||||
ClientAutoWalk = 100,
|
||||
ClientWalkNorth = 101,
|
||||
ClientWalkEast = 102,
|
||||
ClientWalkSouth = 103,
|
||||
ClientWalkWest = 104,
|
||||
ClientStop = 105,
|
||||
ClientWalkNorthEast = 106,
|
||||
ClientWalkSouthEast = 107,
|
||||
ClientWalkSouthWest = 108,
|
||||
ClientWalkNorthWest = 109,
|
||||
ClientTurnNorth = 111,
|
||||
ClientTurnEast = 112,
|
||||
ClientTurnSouth = 113,
|
||||
ClientTurnWest = 114,
|
||||
ClientEquipItem = 119, // 910
|
||||
ClientMove = 120,
|
||||
ClientInspectNpcTrade = 121,
|
||||
ClientBuyItem = 122,
|
||||
ClientSellItem = 123,
|
||||
ClientCloseNpcTrade = 124,
|
||||
ClientRequestTrade = 125,
|
||||
ClientInspectTrade = 126,
|
||||
ClientAcceptTrade = 127,
|
||||
ClientRejectTrade = 128,
|
||||
ClientUseItem = 130,
|
||||
ClientUseItemWith = 131,
|
||||
ClientUseOnCreature = 132,
|
||||
ClientRotateItem = 133,
|
||||
ClientCloseContainer = 135,
|
||||
ClientUpContainer = 136,
|
||||
ClientEditText = 137,
|
||||
ClientEditList = 138,
|
||||
ClientLook = 140,
|
||||
ClientLookCreature = 141,
|
||||
ClientTalk = 150,
|
||||
ClientRequestChannels = 151,
|
||||
ClientJoinChannel = 152,
|
||||
ClientLeaveChannel = 153,
|
||||
ClientOpenPrivateChannel = 154,
|
||||
ClientCloseNpcChannel = 158,
|
||||
ClientChangeFightModes = 160,
|
||||
ClientAttack = 161,
|
||||
ClientFollow = 162,
|
||||
ClientInviteToParty = 163,
|
||||
ClientJoinParty = 164,
|
||||
ClientRevokeInvitation = 165,
|
||||
ClientPassLeadership = 166,
|
||||
ClientLeaveParty = 167,
|
||||
ClientShareExperience = 168,
|
||||
ClientDisbandParty = 169,
|
||||
ClientOpenOwnChannel = 170,
|
||||
ClientInviteToOwnChannel = 171,
|
||||
ClientExcludeFromOwnChannel = 172,
|
||||
ClientCancelAttackAndFollow = 190,
|
||||
ClientUpdateTile = 201,
|
||||
ClientRefreshContainer = 202,
|
||||
ClientRequestOutfit = 210,
|
||||
ClientChangeOutfit = 211,
|
||||
ClientMount = 212, // 870
|
||||
ClientAddVip = 220,
|
||||
ClientRemoveVip = 221,
|
||||
ClientBugReport = 230,
|
||||
ClientRuleViolation = 231,
|
||||
ClientDebugReport = 232,
|
||||
ClientRequestQuestLog = 240,
|
||||
ClientRequestQuestLine = 241,
|
||||
ClientNewRuleViolation = 242, // 910
|
||||
ClientRequestItemInfo = 243, // 910
|
||||
ClientMarketLeave = 244, // 944
|
||||
ClientMarketBrowse = 245, // 944
|
||||
ClientMarketCreate = 246, // 944
|
||||
ClientMarketCancel = 247, // 944
|
||||
ClientMarketAccept = 248, // 944
|
||||
ClientAnswerModalDialog = 249 // 960
|
||||
};
|
||||
|
||||
enum CreatureType {
|
||||
CreatureTypePlayer = 0,
|
||||
CreatureTypeMonster,
|
||||
CreatureTypeNpc
|
||||
};
|
||||
|
||||
enum CreaturesIdRange {
|
||||
PlayerStartId = 0x10000000,
|
||||
PlayerEndId = 0x40000000,
|
||||
MonsterStartId = 0x40000000,
|
||||
MonsterEndId = 0x80000000,
|
||||
NpcStartId = 0x80000000,
|
||||
NpcEndId = 0xffffffff
|
||||
};
|
||||
|
||||
void buildMessageModesMap(int version);
|
||||
Otc::MessageMode translateMessageModeFromServer(uint8 mode);
|
||||
uint8 translateMessageModeToServer(Otc::MessageMode mode);
|
||||
}
|
||||
|
||||
#endif
|
||||
77
src/client/protocolgame.cpp
Normal file
77
src/client/protocolgame.cpp
Normal file
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Copyright (c) 2010-2013 OTClient <https://github.com/edubart/otclient>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "protocolgame.h"
|
||||
#include "game.h"
|
||||
#include "player.h"
|
||||
#include "item.h"
|
||||
#include "localplayer.h"
|
||||
|
||||
void ProtocolGame::login(const std::string& accountName, const std::string& accountPassword, const std::string& host, uint16 port, const std::string& characterName)
|
||||
{
|
||||
m_accountName = accountName;
|
||||
m_accountPassword = accountPassword;
|
||||
m_characterName = characterName;
|
||||
|
||||
connect(host, port);
|
||||
}
|
||||
|
||||
void ProtocolGame::onConnect()
|
||||
{
|
||||
m_firstRecv = true;
|
||||
Protocol::onConnect();
|
||||
|
||||
m_localPlayer = g_game.getLocalPlayer();
|
||||
|
||||
if(g_game.getFeature(Otc::GameProtocolChecksum))
|
||||
enableChecksum();
|
||||
|
||||
if(!g_game.getFeature(Otc::GameChallangeOnLogin))
|
||||
sendLoginPacket(0, 0);
|
||||
|
||||
recv();
|
||||
}
|
||||
|
||||
void ProtocolGame::onRecv(const InputMessagePtr& inputMessage)
|
||||
{
|
||||
if(m_firstRecv) {
|
||||
m_firstRecv = false;
|
||||
|
||||
if(g_game.getProtocolVersion() > 810) {
|
||||
int size = inputMessage->getU16();
|
||||
if(size != inputMessage->getUnreadSize()) {
|
||||
g_logger.traceError("invalid message size");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
parseMessage(inputMessage);
|
||||
recv();
|
||||
}
|
||||
|
||||
void ProtocolGame::onError(const boost::system::error_code& error)
|
||||
{
|
||||
Protocol::onError(error);
|
||||
|
||||
g_game.processConnectionError(error);
|
||||
}
|
||||
233
src/client/protocolgame.h
Normal file
233
src/client/protocolgame.h
Normal file
@@ -0,0 +1,233 @@
|
||||
/*
|
||||
* Copyright (c) 2010-2013 OTClient <https://github.com/edubart/otclient>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef PROTOCOLGAME_H
|
||||
#define PROTOCOLGAME_H
|
||||
|
||||
#include "declarations.h"
|
||||
#include "protocolcodes.h"
|
||||
#include <framework/net/protocol.h>
|
||||
#include "creature.h"
|
||||
|
||||
class ProtocolGame : public Protocol
|
||||
{
|
||||
public:
|
||||
void login(const std::string& accountName, const std::string& accountPassword, const std::string& host, uint16 port, const std::string& characterName);
|
||||
void send(const OutputMessagePtr& outputMessage);
|
||||
|
||||
void sendExtendedOpcode(uint8 opcode, const std::string& buffer);
|
||||
void sendLoginPacket(uint challangeTimestamp, uint8 challangeRandom);
|
||||
void sendEnterGame();
|
||||
void sendLogout();
|
||||
void sendPing();
|
||||
void sendPingBack();
|
||||
void sendAutoWalk(const std::vector<Otc::Direction>& path);
|
||||
void sendWalkNorth();
|
||||
void sendWalkEast();
|
||||
void sendWalkSouth();
|
||||
void sendWalkWest();
|
||||
void sendStop();
|
||||
void sendWalkNorthEast();
|
||||
void sendWalkSouthEast();
|
||||
void sendWalkSouthWest();
|
||||
void sendWalkNorthWest();
|
||||
void sendTurnNorth();
|
||||
void sendTurnEast();
|
||||
void sendTurnSouth();
|
||||
void sendTurnWest();
|
||||
void sendEquipItem(int itemId, int countOrSubType);
|
||||
void sendMove(const Position& fromPos, int itemId, int stackpos, const Position& toPos, int count);
|
||||
void sendInspectNpcTrade(int itemId, int count);
|
||||
void sendBuyItem(int itemId, int subType, int amount, bool ignoreCapacity, bool buyWithBackpack);
|
||||
void sendSellItem(int itemId, int subType, int amount, bool ignoreEquipped);
|
||||
void sendCloseNpcTrade();
|
||||
void sendRequestTrade(const Position& pos, int thingId, int stackpos, uint playerId);
|
||||
void sendInspectTrade(bool counterOffer, int index);
|
||||
void sendAcceptTrade();
|
||||
void sendRejectTrade();
|
||||
void sendUseItem(const Position& position, int itemId, int stackpos, int index);
|
||||
void sendUseItemWith(const Position& fromPos, int itemId, int fromStackpos, const Position& toPos, int toThingId, int toStackpos);
|
||||
void sendUseOnCreature(const Position& pos, int thingId, int stackpos, uint creatureId);
|
||||
void sendRotateItem(const Position& pos, int thingId, int stackpos);
|
||||
void sendCloseContainer(int containerId);
|
||||
void sendUpContainer(int containerId);
|
||||
void sendEditText(uint id, const std::string& text);
|
||||
void sendEditList(uint id, int doorId, const std::string& text);
|
||||
void sendLook(const Position& position, int thingId, int stackpos);
|
||||
void sendLookCreature(uint creatureId);
|
||||
void sendTalk(Otc::MessageMode mode, int channelId, const std::string& receiver, const std::string& message);
|
||||
void sendRequestChannels();
|
||||
void sendJoinChannel(int channelId);
|
||||
void sendLeaveChannel(int channelId);
|
||||
void sendOpenPrivateChannel(const std::string& receiver);
|
||||
void sendCloseNpcChannel();
|
||||
void sendChangeFightModes(Otc::FightModes fightMode, Otc::ChaseModes chaseMode, bool safeFight);
|
||||
void sendAttack(uint creatureId, uint seq);
|
||||
void sendFollow(uint creatureId, uint seq);
|
||||
void sendInviteToParty(uint creatureId);
|
||||
void sendJoinParty(uint creatureId);
|
||||
void sendRevokeInvitation(uint creatureId);
|
||||
void sendPassLeadership(uint creatureId);
|
||||
void sendLeaveParty();
|
||||
void sendShareExperience(bool active);
|
||||
void sendOpenOwnChannel();
|
||||
void sendInviteToOwnChannel(const std::string& name);
|
||||
void sendExcludeFromOwnChannel(const std::string& name);
|
||||
void sendCancelAttackAndFollow();
|
||||
void sendRefreshContainer(int containerId);
|
||||
void sendRequestOutfit();
|
||||
void sendChangeOutfit(const Outfit& outfit);
|
||||
void sendMountStatus(bool mount);
|
||||
void sendAddVip(const std::string& name);
|
||||
void sendRemoveVip(uint playerId);
|
||||
void sendBugReport(const std::string& comment);
|
||||
void sendRuleViolation(const std::string& target, int reason, int action, const std::string& comment, const std::string& statement, int statementId, bool ipBanishment);
|
||||
void sendDebugReport(const std::string& a, const std::string& b, const std::string& c, const std::string& d);
|
||||
void sendRequestQuestLog();
|
||||
void sendRequestQuestLine(int questId);
|
||||
void sendNewNewRuleViolation(int reason, int action, const std::string& characterName, const std::string& comment, const std::string& translation);
|
||||
void sendRequestItemInfo(int itemId, int subType, int index);
|
||||
void sendAnswerModalDialog(int dialog, int button, int choice);
|
||||
|
||||
protected:
|
||||
void onConnect();
|
||||
void onRecv(const InputMessagePtr& inputMessage);
|
||||
void onError(const boost::system::error_code& error);
|
||||
|
||||
friend class Game;
|
||||
|
||||
public:
|
||||
void addPosition(const OutputMessagePtr& msg, const Position& position);
|
||||
|
||||
private:
|
||||
void parseMessage(const InputMessagePtr& msg);
|
||||
void parsePendingGame(const InputMessagePtr& msg);
|
||||
void parseEnterGame(const InputMessagePtr& msg);
|
||||
void parseInitGame(const InputMessagePtr& msg);
|
||||
void parseGMActions(const InputMessagePtr& msg);
|
||||
void parseLoginError(const InputMessagePtr& msg);
|
||||
void parseLoginAdvice(const InputMessagePtr& msg);
|
||||
void parseLoginWait(const InputMessagePtr& msg);
|
||||
void parsePing(const InputMessagePtr& msg);
|
||||
void parsePingBack(const InputMessagePtr& msg);
|
||||
void parseChallange(const InputMessagePtr& msg);
|
||||
void parseDeath(const InputMessagePtr& msg);
|
||||
void parseMapDescription(const InputMessagePtr& msg);
|
||||
void parseMapMoveNorth(const InputMessagePtr& msg);
|
||||
void parseMapMoveEast(const InputMessagePtr& msg);
|
||||
void parseMapMoveSouth(const InputMessagePtr& msg);
|
||||
void parseMapMoveWest(const InputMessagePtr& msg);
|
||||
void parseUpdateTile(const InputMessagePtr& msg);
|
||||
void parseTileAddThing(const InputMessagePtr& msg);
|
||||
void parseTileTransformThing(const InputMessagePtr& msg);
|
||||
void parseTileRemoveThing(const InputMessagePtr& msg);
|
||||
void parseCreatureMove(const InputMessagePtr& msg);
|
||||
void parseOpenContainer(const InputMessagePtr& msg);
|
||||
void parseCloseContainer(const InputMessagePtr& msg);
|
||||
void parseContainerAddItem(const InputMessagePtr& msg);
|
||||
void parseContainerUpdateItem(const InputMessagePtr& msg);
|
||||
void parseContainerRemoveItem(const InputMessagePtr& msg);
|
||||
void parseAddInventoryItem(const InputMessagePtr& msg);
|
||||
void parseRemoveInventoryItem(const InputMessagePtr& msg);
|
||||
void parseOpenNpcTrade(const InputMessagePtr& msg);
|
||||
void parsePlayerGoods(const InputMessagePtr& msg);
|
||||
void parseCloseNpcTrade(const InputMessagePtr&);
|
||||
void parseWorldLight(const InputMessagePtr& msg);
|
||||
void parseMagicEffect(const InputMessagePtr& msg);
|
||||
void parseAnimatedText(const InputMessagePtr& msg);
|
||||
void parseDistanceMissile(const InputMessagePtr& msg);
|
||||
void parseCreatureMark(const InputMessagePtr& msg);
|
||||
void parseTrappers(const InputMessagePtr& msg);
|
||||
void parseCreatureHealth(const InputMessagePtr& msg);
|
||||
void parseCreatureLight(const InputMessagePtr& msg);
|
||||
void parseCreatureOutfit(const InputMessagePtr& msg);
|
||||
void parseCreatureSpeed(const InputMessagePtr& msg);
|
||||
void parseCreatureSkulls(const InputMessagePtr& msg);
|
||||
void parseCreatureShields(const InputMessagePtr& msg);
|
||||
void parseCreatureUnpass(const InputMessagePtr& msg);
|
||||
void parseEditText(const InputMessagePtr& msg);
|
||||
void parseEditList(const InputMessagePtr& msg);
|
||||
void parsePlayerInfo(const InputMessagePtr& msg);
|
||||
void parsePlayerStats(const InputMessagePtr& msg);
|
||||
void parsePlayerSkills(const InputMessagePtr& msg);
|
||||
void parsePlayerState(const InputMessagePtr& msg);
|
||||
void parsePlayerCancelAttack(const InputMessagePtr& msg);
|
||||
void parseSpellCooldown(const InputMessagePtr& msg);
|
||||
void parseSpellGroupCooldown(const InputMessagePtr& msg);
|
||||
void parseMultiUseCooldown(const InputMessagePtr& msg);
|
||||
void parseTalk(const InputMessagePtr& msg);
|
||||
void parseChannelList(const InputMessagePtr& msg);
|
||||
void parseOpenChannel(const InputMessagePtr& msg);
|
||||
void parseOpenPrivateChannel(const InputMessagePtr& msg);
|
||||
void parseOpenOwnPrivateChannel(const InputMessagePtr& msg);
|
||||
void parseCloseChannel(const InputMessagePtr& msg);
|
||||
void parseRuleViolationChannel(const InputMessagePtr& msg);
|
||||
void parseRuleViolationRemove(const InputMessagePtr& msg);
|
||||
void parseRuleViolationCancel(const InputMessagePtr& msg);
|
||||
void parseRuleViolationLock(const InputMessagePtr& msg);
|
||||
void parseOwnTrade(const InputMessagePtr& msg);
|
||||
void parseCounterTrade(const InputMessagePtr& msg);
|
||||
void parseCloseTrade(const InputMessagePtr&);
|
||||
void parseTextMessage(const InputMessagePtr& msg);
|
||||
void parseCancelWalk(const InputMessagePtr& msg);
|
||||
void parseWalkWait(const InputMessagePtr& msg);
|
||||
void parseFloorChangeUp(const InputMessagePtr& msg);
|
||||
void parseFloorChangeDown(const InputMessagePtr& msg);
|
||||
void parseOpenOutfitWindow(const InputMessagePtr& msg);
|
||||
void parseVipAdd(const InputMessagePtr& msg);
|
||||
void parseVipState(const InputMessagePtr& msg);
|
||||
void parseVipLogout(const InputMessagePtr& msg);
|
||||
void parseTutorialHint(const InputMessagePtr& msg);
|
||||
void parseAutomapFlag(const InputMessagePtr& msg);
|
||||
void parseQuestLog(const InputMessagePtr& msg);
|
||||
void parseQuestLine(const InputMessagePtr& msg);
|
||||
void parseChannelEvent(const InputMessagePtr& msg);
|
||||
void parseItemInfo(const InputMessagePtr& msg);
|
||||
void parsePlayerInventory(const InputMessagePtr& msg);
|
||||
void parseShowModalDialog(const InputMessagePtr& msg);
|
||||
void parseExtendedOpcode(const InputMessagePtr& msg);
|
||||
|
||||
public:
|
||||
void setMapDescription(const InputMessagePtr& msg, int x, int y, int z, int width, int height);
|
||||
int setFloorDescription(const InputMessagePtr& msg, int x, int y, int z, int width, int height, int offset, int skip);
|
||||
int setTileDescription(const InputMessagePtr& msg, Position position);
|
||||
|
||||
Outfit getOutfit(const InputMessagePtr& msg);
|
||||
ThingPtr getThing(const InputMessagePtr& msg);
|
||||
ThingPtr getMappedThing(const InputMessagePtr& msg);
|
||||
CreaturePtr getCreature(const InputMessagePtr& msg, int type = 0);
|
||||
ItemPtr getItem(const InputMessagePtr& msg, int id = 0);
|
||||
Position getPosition(const InputMessagePtr& msg);
|
||||
|
||||
private:
|
||||
stdext::boolean<false> m_enableSendExtendedOpcode;
|
||||
stdext::boolean<false> m_gameInitialized;
|
||||
stdext::boolean<false> m_mapKnown;
|
||||
stdext::boolean<true> m_firstRecv;
|
||||
std::string m_accountName;
|
||||
std::string m_accountPassword;
|
||||
std::string m_characterName;
|
||||
stdext::timer m_pingTimer;
|
||||
LocalPlayerPtr m_localPlayer;
|
||||
};
|
||||
|
||||
#endif
|
||||
1755
src/client/protocolgameparse.cpp
Normal file
1755
src/client/protocolgameparse.cpp
Normal file
File diff suppressed because it is too large
Load Diff
782
src/client/protocolgamesend.cpp
Normal file
782
src/client/protocolgamesend.cpp
Normal file
@@ -0,0 +1,782 @@
|
||||
/*
|
||||
* Copyright (c) 2010-2013 OTClient <https://github.com/edubart/otclient>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "protocolgame.h"
|
||||
#include "game.h"
|
||||
|
||||
void ProtocolGame::send(const OutputMessagePtr& outputMessage)
|
||||
{
|
||||
// avoid usage of automated sends (bot modules)
|
||||
if(!g_game.checkBotProtection())
|
||||
return;
|
||||
Protocol::send(outputMessage);
|
||||
}
|
||||
|
||||
void ProtocolGame::sendExtendedOpcode(uint8 opcode, const std::string& buffer)
|
||||
{
|
||||
if(m_enableSendExtendedOpcode) {
|
||||
OutputMessagePtr msg(new OutputMessage);
|
||||
msg->addU8(Proto::ClientExtendedOpcode);
|
||||
msg->addU8(opcode);
|
||||
msg->addString(buffer);
|
||||
send(msg);
|
||||
} else {
|
||||
g_logger.error(stdext::format("Unable to send extended opcode %d, extended opcodes are not enabled", opcode));
|
||||
}
|
||||
}
|
||||
|
||||
void ProtocolGame::sendLoginPacket(uint challangeTimestamp, uint8 challangeRandom)
|
||||
{
|
||||
OutputMessagePtr msg(new OutputMessage);
|
||||
|
||||
msg->addU8(Proto::ClientPendingGame);
|
||||
|
||||
msg->addU16(g_lua.callGlobalField<int>("g_game", "getOsType"));
|
||||
msg->addU16(g_game.getProtocolVersion());
|
||||
|
||||
if(g_game.getProtocolVersion() >= 971) {
|
||||
msg->addU32(g_game.getClientVersion());
|
||||
msg->addU8(0); // clientType
|
||||
}
|
||||
|
||||
int paddingBytes = 128;
|
||||
msg->addU8(0); // first RSA byte must be 0
|
||||
paddingBytes -= 1;
|
||||
|
||||
// xtea key
|
||||
generateXteaKey();
|
||||
msg->addU32(m_xteaKey[0]);
|
||||
msg->addU32(m_xteaKey[1]);
|
||||
msg->addU32(m_xteaKey[2]);
|
||||
msg->addU32(m_xteaKey[3]);
|
||||
msg->addU8(0); // is gm set?
|
||||
paddingBytes -= 17;
|
||||
|
||||
if(g_game.getFeature(Otc::GameProtocolChecksum))
|
||||
enableChecksum();
|
||||
|
||||
if(g_game.getFeature(Otc::GameAccountNames)) {
|
||||
msg->addString(m_accountName);
|
||||
msg->addString(m_characterName);
|
||||
msg->addString(m_accountPassword);
|
||||
paddingBytes -= 6 + m_accountName.length() + m_characterName.length() + m_accountPassword.length();
|
||||
} else {
|
||||
msg->addU32(stdext::from_string<uint32>(m_accountName));
|
||||
msg->addString(m_characterName);
|
||||
msg->addString(m_accountPassword);
|
||||
paddingBytes -= 8 + m_characterName.length() + m_accountPassword.length();
|
||||
}
|
||||
|
||||
if(g_game.getFeature(Otc::GameChallangeOnLogin)) {
|
||||
msg->addU32(challangeTimestamp);
|
||||
msg->addU8(challangeRandom);
|
||||
paddingBytes -= 5;
|
||||
}
|
||||
|
||||
// complete the 128 bytes for rsa encryption with zeros
|
||||
msg->addPaddingBytes(paddingBytes);
|
||||
|
||||
// encrypt with RSA
|
||||
msg->encryptRsa(128);
|
||||
|
||||
send(msg);
|
||||
|
||||
enableXteaEncryption();
|
||||
}
|
||||
|
||||
void ProtocolGame::sendEnterGame()
|
||||
{
|
||||
OutputMessagePtr msg(new OutputMessage);
|
||||
msg->addU8(Proto::ClientEnterGame);
|
||||
send(msg);
|
||||
}
|
||||
|
||||
void ProtocolGame::sendLogout()
|
||||
{
|
||||
OutputMessagePtr msg(new OutputMessage);
|
||||
msg->addU8(Proto::ClientLeaveGame);
|
||||
send(msg);
|
||||
}
|
||||
|
||||
void ProtocolGame::sendPing()
|
||||
{
|
||||
OutputMessagePtr msg(new OutputMessage);
|
||||
msg->addU8(Proto::ClientPing);
|
||||
m_pingTimer.restart();
|
||||
Protocol::send(msg);
|
||||
}
|
||||
|
||||
void ProtocolGame::sendPingBack()
|
||||
{
|
||||
OutputMessagePtr msg(new OutputMessage);
|
||||
msg->addU8(Proto::ClientPingBack);
|
||||
send(msg);
|
||||
}
|
||||
|
||||
void ProtocolGame::sendAutoWalk(const std::vector<Otc::Direction>& path)
|
||||
{
|
||||
OutputMessagePtr msg(new OutputMessage);
|
||||
msg->addU8(Proto::ClientAutoWalk);
|
||||
msg->addU8(path.size());
|
||||
for(Otc::Direction dir : path) {
|
||||
uint8 byte;
|
||||
switch(dir) {
|
||||
case Otc::East:
|
||||
byte = 1;
|
||||
break;
|
||||
case Otc::NorthEast:
|
||||
byte = 2;
|
||||
break;
|
||||
case Otc::North:
|
||||
byte = 3;
|
||||
break;
|
||||
case Otc::NorthWest:
|
||||
byte = 4;
|
||||
break;
|
||||
case Otc::West:
|
||||
byte = 5;
|
||||
break;
|
||||
case Otc::SouthWest:
|
||||
byte = 6;
|
||||
break;
|
||||
case Otc::South:
|
||||
byte = 7;
|
||||
break;
|
||||
case Otc::SouthEast:
|
||||
byte = 8;
|
||||
break;
|
||||
default:
|
||||
byte = 0;
|
||||
break;
|
||||
}
|
||||
msg->addU8(byte);
|
||||
}
|
||||
send(msg);
|
||||
}
|
||||
|
||||
void ProtocolGame::sendWalkNorth()
|
||||
{
|
||||
OutputMessagePtr msg(new OutputMessage);
|
||||
msg->addU8(Proto::ClientWalkNorth);
|
||||
send(msg);
|
||||
}
|
||||
|
||||
void ProtocolGame::sendWalkEast()
|
||||
{
|
||||
OutputMessagePtr msg(new OutputMessage);
|
||||
msg->addU8(Proto::ClientWalkEast);
|
||||
send(msg);
|
||||
}
|
||||
|
||||
void ProtocolGame::sendWalkSouth()
|
||||
{
|
||||
OutputMessagePtr msg(new OutputMessage);
|
||||
msg->addU8(Proto::ClientWalkSouth);
|
||||
send(msg);
|
||||
}
|
||||
|
||||
void ProtocolGame::sendWalkWest()
|
||||
{
|
||||
OutputMessagePtr msg(new OutputMessage);
|
||||
msg->addU8(Proto::ClientWalkWest);
|
||||
send(msg);
|
||||
}
|
||||
|
||||
void ProtocolGame::sendStop()
|
||||
{
|
||||
OutputMessagePtr msg(new OutputMessage);
|
||||
msg->addU8(Proto::ClientStop);
|
||||
send(msg);
|
||||
}
|
||||
|
||||
void ProtocolGame::sendWalkNorthEast()
|
||||
{
|
||||
OutputMessagePtr msg(new OutputMessage);
|
||||
msg->addU8(Proto::ClientWalkNorthEast);
|
||||
send(msg);
|
||||
}
|
||||
|
||||
void ProtocolGame::sendWalkSouthEast()
|
||||
{
|
||||
OutputMessagePtr msg(new OutputMessage);
|
||||
msg->addU8(Proto::ClientWalkSouthEast);
|
||||
send(msg);
|
||||
}
|
||||
|
||||
void ProtocolGame::sendWalkSouthWest()
|
||||
{
|
||||
OutputMessagePtr msg(new OutputMessage);
|
||||
msg->addU8(Proto::ClientWalkSouthWest);
|
||||
send(msg);
|
||||
}
|
||||
|
||||
void ProtocolGame::sendWalkNorthWest()
|
||||
{
|
||||
OutputMessagePtr msg(new OutputMessage);
|
||||
msg->addU8(Proto::ClientWalkNorthWest);
|
||||
send(msg);
|
||||
}
|
||||
|
||||
void ProtocolGame::sendTurnNorth()
|
||||
{
|
||||
OutputMessagePtr msg(new OutputMessage);
|
||||
msg->addU8(Proto::ClientTurnNorth);
|
||||
send(msg);
|
||||
}
|
||||
|
||||
void ProtocolGame::sendTurnEast()
|
||||
{
|
||||
OutputMessagePtr msg(new OutputMessage);
|
||||
msg->addU8(Proto::ClientTurnEast);
|
||||
send(msg);
|
||||
}
|
||||
|
||||
void ProtocolGame::sendTurnSouth()
|
||||
{
|
||||
OutputMessagePtr msg(new OutputMessage);
|
||||
msg->addU8(Proto::ClientTurnSouth);
|
||||
send(msg);
|
||||
}
|
||||
|
||||
void ProtocolGame::sendTurnWest()
|
||||
{
|
||||
OutputMessagePtr msg(new OutputMessage);
|
||||
msg->addU8(Proto::ClientTurnWest);
|
||||
send(msg);
|
||||
}
|
||||
|
||||
void ProtocolGame::sendEquipItem(int itemId, int countOrSubType)
|
||||
{
|
||||
OutputMessagePtr msg(new OutputMessage);
|
||||
msg->addU8(Proto::ClientEquipItem);
|
||||
msg->addU16(itemId);
|
||||
msg->addU8(countOrSubType);
|
||||
send(msg);
|
||||
}
|
||||
|
||||
void ProtocolGame::sendMove(const Position& fromPos, int thingId, int stackpos, const Position& toPos, int count)
|
||||
{
|
||||
OutputMessagePtr msg(new OutputMessage);
|
||||
msg->addU8(Proto::ClientMove);
|
||||
addPosition(msg, fromPos);
|
||||
msg->addU16(thingId);
|
||||
msg->addU8(stackpos);
|
||||
addPosition(msg, toPos);
|
||||
msg->addU8(count);
|
||||
send(msg);
|
||||
}
|
||||
|
||||
void ProtocolGame::sendInspectNpcTrade(int itemId, int count)
|
||||
{
|
||||
OutputMessagePtr msg(new OutputMessage);
|
||||
msg->addU8(Proto::ClientInspectNpcTrade);
|
||||
msg->addU16(itemId);
|
||||
msg->addU8(count);
|
||||
send(msg);
|
||||
}
|
||||
|
||||
void ProtocolGame::sendBuyItem(int itemId, int subType, int amount, bool ignoreCapacity, bool buyWithBackpack)
|
||||
{
|
||||
OutputMessagePtr msg(new OutputMessage);
|
||||
msg->addU8(Proto::ClientBuyItem);
|
||||
msg->addU16(itemId);
|
||||
msg->addU8(subType);
|
||||
msg->addU8(amount);
|
||||
msg->addU8(ignoreCapacity ? 0x01 : 0x00);
|
||||
msg->addU8(buyWithBackpack ? 0x01 : 0x00);
|
||||
send(msg);
|
||||
}
|
||||
|
||||
void ProtocolGame::sendSellItem(int itemId, int subType, int amount, bool ignoreEquipped)
|
||||
{
|
||||
OutputMessagePtr msg(new OutputMessage);
|
||||
msg->addU8(Proto::ClientSellItem);
|
||||
msg->addU16(itemId);
|
||||
msg->addU8(subType);
|
||||
msg->addU8(amount);
|
||||
msg->addU8(ignoreEquipped ? 0x01 : 0x00);
|
||||
send(msg);
|
||||
}
|
||||
|
||||
void ProtocolGame::sendCloseNpcTrade()
|
||||
{
|
||||
OutputMessagePtr msg(new OutputMessage);
|
||||
msg->addU8(Proto::ClientCloseNpcTrade);
|
||||
send(msg);
|
||||
}
|
||||
|
||||
void ProtocolGame::sendRequestTrade(const Position& pos, int thingId, int stackpos, uint creatureId)
|
||||
{
|
||||
OutputMessagePtr msg(new OutputMessage);
|
||||
msg->addU8(Proto::ClientRequestTrade);
|
||||
addPosition(msg, pos);
|
||||
msg->addU16(thingId);
|
||||
msg->addU8(stackpos);
|
||||
msg->addU32(creatureId);
|
||||
send(msg);
|
||||
}
|
||||
|
||||
void ProtocolGame::sendInspectTrade(bool counterOffer, int index)
|
||||
{
|
||||
OutputMessagePtr msg(new OutputMessage);
|
||||
msg->addU8(Proto::ClientInspectTrade);
|
||||
msg->addU8(counterOffer ? 0x01 : 0x00);
|
||||
msg->addU8(index);
|
||||
send(msg);
|
||||
}
|
||||
|
||||
void ProtocolGame::sendAcceptTrade()
|
||||
{
|
||||
OutputMessagePtr msg(new OutputMessage);
|
||||
msg->addU8(Proto::ClientAcceptTrade);
|
||||
send(msg);
|
||||
}
|
||||
|
||||
void ProtocolGame::sendRejectTrade()
|
||||
{
|
||||
OutputMessagePtr msg(new OutputMessage);
|
||||
msg->addU8(Proto::ClientRejectTrade);
|
||||
send(msg);
|
||||
}
|
||||
|
||||
void ProtocolGame::sendUseItem(const Position& position, int itemId, int stackpos, int index)
|
||||
{
|
||||
OutputMessagePtr msg(new OutputMessage);
|
||||
msg->addU8(Proto::ClientUseItem);
|
||||
addPosition(msg, position);
|
||||
msg->addU16(itemId);
|
||||
msg->addU8(stackpos);
|
||||
msg->addU8(index);
|
||||
send(msg);
|
||||
}
|
||||
|
||||
void ProtocolGame::sendUseItemWith(const Position& fromPos, int itemId, int fromStackpos, const Position& toPos, int toThingId, int toStackpos)
|
||||
{
|
||||
OutputMessagePtr msg(new OutputMessage);
|
||||
msg->addU8(Proto::ClientUseItemWith);
|
||||
addPosition(msg, fromPos);
|
||||
msg->addU16(itemId);
|
||||
msg->addU8(fromStackpos);
|
||||
addPosition(msg, toPos);
|
||||
msg->addU16(toThingId);
|
||||
msg->addU8(toStackpos);
|
||||
send(msg);
|
||||
}
|
||||
|
||||
void ProtocolGame::sendUseOnCreature(const Position& pos, int thingId, int stackpos, uint creatureId)
|
||||
{
|
||||
OutputMessagePtr msg(new OutputMessage);
|
||||
msg->addU8(Proto::ClientUseOnCreature);
|
||||
addPosition(msg, pos);
|
||||
msg->addU16(thingId);
|
||||
msg->addU8(stackpos);
|
||||
msg->addU32(creatureId);
|
||||
send(msg);
|
||||
}
|
||||
|
||||
void ProtocolGame::sendRotateItem(const Position& pos, int thingId, int stackpos)
|
||||
{
|
||||
OutputMessagePtr msg(new OutputMessage);
|
||||
msg->addU8(Proto::ClientRotateItem);
|
||||
addPosition(msg, pos);
|
||||
msg->addU16(thingId);
|
||||
msg->addU8(stackpos);
|
||||
send(msg);
|
||||
}
|
||||
|
||||
void ProtocolGame::sendCloseContainer(int containerId)
|
||||
{
|
||||
OutputMessagePtr msg(new OutputMessage);
|
||||
msg->addU8(Proto::ClientCloseContainer);
|
||||
msg->addU8(containerId);
|
||||
send(msg);
|
||||
}
|
||||
|
||||
void ProtocolGame::sendUpContainer(int containerId)
|
||||
{
|
||||
OutputMessagePtr msg(new OutputMessage);
|
||||
msg->addU8(Proto::ClientUpContainer);
|
||||
msg->addU8(containerId);
|
||||
send(msg);
|
||||
}
|
||||
|
||||
void ProtocolGame::sendEditText(uint id, const std::string& text)
|
||||
{
|
||||
OutputMessagePtr msg(new OutputMessage);
|
||||
msg->addU8(Proto::ClientEditText);
|
||||
msg->addU32(id);
|
||||
msg->addString(text);
|
||||
send(msg);
|
||||
}
|
||||
|
||||
void ProtocolGame::sendEditList(uint id, int doorId, const std::string& text)
|
||||
{
|
||||
OutputMessagePtr msg(new OutputMessage);
|
||||
msg->addU8(Proto::ClientEditList);
|
||||
msg->addU8(doorId);
|
||||
msg->addU32(id);
|
||||
msg->addString(text);
|
||||
send(msg);
|
||||
}
|
||||
|
||||
void ProtocolGame::sendLook(const Position& position, int thingId, int stackpos)
|
||||
{
|
||||
OutputMessagePtr msg(new OutputMessage);
|
||||
msg->addU8(Proto::ClientLook);
|
||||
addPosition(msg, position);
|
||||
msg->addU16(thingId);
|
||||
msg->addU8(stackpos);
|
||||
send(msg);
|
||||
}
|
||||
|
||||
void ProtocolGame::sendLookCreature(uint32 creatureId)
|
||||
{
|
||||
OutputMessagePtr msg(new OutputMessage);
|
||||
msg->addU8(Proto::ClientLookCreature);
|
||||
msg->addU32(creatureId);
|
||||
send(msg);
|
||||
}
|
||||
|
||||
void ProtocolGame::sendTalk(Otc::MessageMode mode, int channelId, const std::string& receiver, const std::string& message)
|
||||
{
|
||||
if(message.empty())
|
||||
return;
|
||||
|
||||
if(message.length() > 255) {
|
||||
g_logger.traceError("message too large");
|
||||
return;
|
||||
}
|
||||
|
||||
OutputMessagePtr msg(new OutputMessage);
|
||||
msg->addU8(Proto::ClientTalk);
|
||||
msg->addU8(Proto::translateMessageModeToServer(mode));
|
||||
|
||||
switch(mode) {
|
||||
case Otc::MessagePrivateTo:
|
||||
case Otc::MessageGamemasterPrivateTo:
|
||||
msg->addString(receiver);
|
||||
break;
|
||||
case Otc::MessageChannel:
|
||||
case Otc::MessageChannelHighlight:
|
||||
case Otc::MessageChannelManagement:
|
||||
case Otc::MessageGamemasterChannel:
|
||||
msg->addU16(channelId);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
msg->addString(message);
|
||||
send(msg);
|
||||
}
|
||||
|
||||
void ProtocolGame::sendRequestChannels()
|
||||
{
|
||||
OutputMessagePtr msg(new OutputMessage);
|
||||
msg->addU8(Proto::ClientRequestChannels);
|
||||
send(msg);
|
||||
}
|
||||
|
||||
void ProtocolGame::sendJoinChannel(int channelId)
|
||||
{
|
||||
OutputMessagePtr msg(new OutputMessage);
|
||||
msg->addU8(Proto::ClientJoinChannel);
|
||||
msg->addU16(channelId);
|
||||
send(msg);
|
||||
}
|
||||
|
||||
void ProtocolGame::sendLeaveChannel(int channelId)
|
||||
{
|
||||
OutputMessagePtr msg(new OutputMessage);
|
||||
msg->addU8(Proto::ClientLeaveChannel);
|
||||
msg->addU16(channelId);
|
||||
send(msg);
|
||||
}
|
||||
|
||||
void ProtocolGame::sendOpenPrivateChannel(const std::string& receiver)
|
||||
{
|
||||
OutputMessagePtr msg(new OutputMessage);
|
||||
msg->addU8(Proto::ClientOpenPrivateChannel);
|
||||
msg->addString(receiver);
|
||||
send(msg);
|
||||
}
|
||||
|
||||
void ProtocolGame::sendCloseNpcChannel()
|
||||
{
|
||||
OutputMessagePtr msg(new OutputMessage);
|
||||
msg->addU8(Proto::ClientCloseNpcChannel);
|
||||
send(msg);
|
||||
}
|
||||
|
||||
void ProtocolGame::sendChangeFightModes(Otc::FightModes fightMode, Otc::ChaseModes chaseMode, bool safeFight)
|
||||
{
|
||||
OutputMessagePtr msg(new OutputMessage);
|
||||
msg->addU8(Proto::ClientChangeFightModes);
|
||||
msg->addU8(fightMode);
|
||||
msg->addU8(chaseMode);
|
||||
msg->addU8(safeFight ? 0x01: 0x00);
|
||||
send(msg);
|
||||
}
|
||||
|
||||
void ProtocolGame::sendAttack(uint creatureId, uint seq)
|
||||
{
|
||||
OutputMessagePtr msg(new OutputMessage);
|
||||
msg->addU8(Proto::ClientAttack);
|
||||
msg->addU32(creatureId);
|
||||
msg->addU32(seq);
|
||||
send(msg);
|
||||
}
|
||||
|
||||
void ProtocolGame::sendFollow(uint creatureId, uint seq)
|
||||
{
|
||||
OutputMessagePtr msg(new OutputMessage);
|
||||
msg->addU8(Proto::ClientFollow);
|
||||
msg->addU32(creatureId);
|
||||
msg->addU32(seq);
|
||||
send(msg);
|
||||
}
|
||||
|
||||
void ProtocolGame::sendInviteToParty(uint creatureId)
|
||||
{
|
||||
OutputMessagePtr msg(new OutputMessage);
|
||||
msg->addU8(Proto::ClientInviteToParty);
|
||||
msg->addU32(creatureId);
|
||||
send(msg);
|
||||
}
|
||||
|
||||
void ProtocolGame::sendJoinParty(uint creatureId)
|
||||
{
|
||||
OutputMessagePtr msg(new OutputMessage);
|
||||
msg->addU8(Proto::ClientJoinParty);
|
||||
msg->addU32(creatureId);
|
||||
send(msg);
|
||||
}
|
||||
|
||||
void ProtocolGame::sendRevokeInvitation(uint creatureId)
|
||||
{
|
||||
OutputMessagePtr msg(new OutputMessage);
|
||||
msg->addU8(Proto::ClientRevokeInvitation);
|
||||
msg->addU32(creatureId);
|
||||
send(msg);
|
||||
}
|
||||
|
||||
void ProtocolGame::sendPassLeadership(uint creatureId)
|
||||
{
|
||||
OutputMessagePtr msg(new OutputMessage);
|
||||
msg->addU8(Proto::ClientPassLeadership);
|
||||
msg->addU32(creatureId);
|
||||
send(msg);
|
||||
}
|
||||
|
||||
void ProtocolGame::sendLeaveParty()
|
||||
{
|
||||
OutputMessagePtr msg(new OutputMessage);
|
||||
msg->addU8(Proto::ClientLeaveParty);
|
||||
send(msg);
|
||||
}
|
||||
|
||||
void ProtocolGame::sendShareExperience(bool active)
|
||||
{
|
||||
OutputMessagePtr msg(new OutputMessage);
|
||||
msg->addU8(Proto::ClientShareExperience);
|
||||
msg->addU8(active ? 0x01 : 0x00);
|
||||
|
||||
if(g_game.getProtocolVersion() < 910)
|
||||
msg->addU8(0);
|
||||
|
||||
send(msg);
|
||||
}
|
||||
|
||||
void ProtocolGame::sendOpenOwnChannel()
|
||||
{
|
||||
OutputMessagePtr msg(new OutputMessage);
|
||||
msg->addU8(Proto::ClientOpenOwnChannel);
|
||||
send(msg);
|
||||
}
|
||||
|
||||
void ProtocolGame::sendInviteToOwnChannel(const std::string& name)
|
||||
{
|
||||
OutputMessagePtr msg(new OutputMessage);
|
||||
msg->addU8(Proto::ClientInviteToOwnChannel);
|
||||
msg->addString(name);
|
||||
send(msg);
|
||||
}
|
||||
|
||||
void ProtocolGame::sendExcludeFromOwnChannel(const std::string& name)
|
||||
{
|
||||
OutputMessagePtr msg(new OutputMessage);
|
||||
msg->addU8(Proto::ClientExcludeFromOwnChannel);
|
||||
msg->addString(name);
|
||||
send(msg);
|
||||
}
|
||||
|
||||
void ProtocolGame::sendCancelAttackAndFollow()
|
||||
{
|
||||
OutputMessagePtr msg(new OutputMessage);
|
||||
msg->addU8(Proto::ClientCancelAttackAndFollow);
|
||||
send(msg);
|
||||
}
|
||||
|
||||
void ProtocolGame::sendRefreshContainer(int containerId)
|
||||
{
|
||||
OutputMessagePtr msg(new OutputMessage);
|
||||
msg->addU8(Proto::ClientRefreshContainer);
|
||||
msg->addU8(containerId);
|
||||
send(msg);
|
||||
}
|
||||
|
||||
void ProtocolGame::sendRequestOutfit()
|
||||
{
|
||||
OutputMessagePtr msg(new OutputMessage);
|
||||
msg->addU8(Proto::ClientRequestOutfit);
|
||||
send(msg);
|
||||
}
|
||||
|
||||
void ProtocolGame::sendChangeOutfit(const Outfit& outfit)
|
||||
{
|
||||
OutputMessagePtr msg(new OutputMessage);
|
||||
msg->addU8(Proto::ClientChangeOutfit);
|
||||
msg->addU16(outfit.getId());
|
||||
msg->addU8(outfit.getHead());
|
||||
msg->addU8(outfit.getBody());
|
||||
msg->addU8(outfit.getLegs());
|
||||
msg->addU8(outfit.getFeet());
|
||||
msg->addU8(outfit.getAddons());
|
||||
if(g_game.getFeature(Otc::GamePlayerMounts))
|
||||
msg->addU16(outfit.getMount());
|
||||
send(msg);
|
||||
}
|
||||
|
||||
void ProtocolGame::sendMountStatus(bool mount)
|
||||
{
|
||||
if(g_game.getFeature(Otc::GamePlayerMounts)) {
|
||||
OutputMessagePtr msg(new OutputMessage);
|
||||
msg->addU8(Proto::ClientMount);
|
||||
msg->addU8(mount);
|
||||
send(msg);
|
||||
} else {
|
||||
g_logger.error("ProtocolGame::sendMountStatus does not support the current protocol.");
|
||||
}
|
||||
}
|
||||
|
||||
void ProtocolGame::sendAddVip(const std::string& name)
|
||||
{
|
||||
OutputMessagePtr msg(new OutputMessage);
|
||||
msg->addU8(Proto::ClientAddVip);
|
||||
msg->addString(name);
|
||||
send(msg);
|
||||
}
|
||||
|
||||
void ProtocolGame::sendRemoveVip(uint playerId)
|
||||
{
|
||||
OutputMessagePtr msg(new OutputMessage);
|
||||
msg->addU8(Proto::ClientRemoveVip);
|
||||
msg->addU32(playerId);
|
||||
send(msg);
|
||||
}
|
||||
|
||||
void ProtocolGame::sendBugReport(const std::string& comment)
|
||||
{
|
||||
OutputMessagePtr msg(new OutputMessage);
|
||||
msg->addU8(Proto::ClientBugReport);
|
||||
msg->addString(comment);
|
||||
send(msg);
|
||||
}
|
||||
|
||||
void ProtocolGame::sendRuleViolation(const std::string& target, int reason, int action, const std::string& comment, const std::string& statement, int statementId, bool ipBanishment)
|
||||
{
|
||||
OutputMessagePtr msg(new OutputMessage);
|
||||
msg->addU8(Proto::ClientRuleViolation);
|
||||
msg->addString(target);
|
||||
msg->addU8(reason);
|
||||
msg->addU8(action);
|
||||
msg->addString(comment);
|
||||
msg->addString(statement);
|
||||
msg->addU16(statementId);
|
||||
msg->addU8(ipBanishment);
|
||||
send(msg);
|
||||
}
|
||||
|
||||
void ProtocolGame::sendDebugReport(const std::string& a, const std::string& b, const std::string& c, const std::string& d)
|
||||
{
|
||||
OutputMessagePtr msg(new OutputMessage);
|
||||
msg->addU8(Proto::ClientDebugReport);
|
||||
msg->addString(a);
|
||||
msg->addString(b);
|
||||
msg->addString(c);
|
||||
msg->addString(d);
|
||||
send(msg);
|
||||
}
|
||||
|
||||
void ProtocolGame::sendRequestQuestLog()
|
||||
{
|
||||
OutputMessagePtr msg(new OutputMessage);
|
||||
msg->addU8(Proto::ClientRequestQuestLog);
|
||||
send(msg);
|
||||
}
|
||||
|
||||
void ProtocolGame::sendRequestQuestLine(int questId)
|
||||
{
|
||||
OutputMessagePtr msg(new OutputMessage);
|
||||
msg->addU8(Proto::ClientRequestQuestLine);
|
||||
msg->addU16(questId);
|
||||
send(msg);
|
||||
}
|
||||
|
||||
void ProtocolGame::sendNewNewRuleViolation(int reason, int action, const std::string& characterName, const std::string& comment, const std::string& translation)
|
||||
{
|
||||
OutputMessagePtr msg(new OutputMessage);
|
||||
msg->addU8(Proto::ClientNewRuleViolation);
|
||||
msg->addU8(reason);
|
||||
msg->addU8(action);
|
||||
msg->addString(characterName);
|
||||
msg->addString(comment);
|
||||
msg->addString(translation);
|
||||
send(msg);
|
||||
}
|
||||
|
||||
void ProtocolGame::sendRequestItemInfo(int itemId, int subType, int index)
|
||||
{
|
||||
OutputMessagePtr msg(new OutputMessage);
|
||||
msg->addU8(Proto::ClientRequestItemInfo);
|
||||
msg->addU8(subType);
|
||||
msg->addU16(itemId);
|
||||
msg->addU8(index);
|
||||
send(msg);
|
||||
}
|
||||
|
||||
void ProtocolGame::sendAnswerModalDialog(int dialog, int button, int choice)
|
||||
{
|
||||
OutputMessagePtr msg(new OutputMessage);
|
||||
msg->addU8(Proto::ClientAnswerModalDialog);
|
||||
msg->addU32(dialog);
|
||||
msg->addU8(button);
|
||||
msg->addU8(choice);
|
||||
send(msg);
|
||||
}
|
||||
|
||||
void ProtocolGame::addPosition(const OutputMessagePtr& msg, const Position& position)
|
||||
{
|
||||
msg->addU16(position.x);
|
||||
msg->addU16(position.y);
|
||||
msg->addU8(position.z);
|
||||
}
|
||||
125
src/client/shadermanager.cpp
Normal file
125
src/client/shadermanager.cpp
Normal file
@@ -0,0 +1,125 @@
|
||||
/*
|
||||
* Copyright (c) 2010-2013 OTClient <https://github.com/edubart/otclient>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "shadermanager.h"
|
||||
#include <framework/graphics/paintershaderprogram.h>
|
||||
#include <framework/graphics/graphics.h>
|
||||
#include <framework/graphics/painterogl2_shadersources.h>
|
||||
|
||||
ShaderManager g_shaders;
|
||||
|
||||
void ShaderManager::init()
|
||||
{
|
||||
if(!g_graphics.canUseShaders())
|
||||
return;
|
||||
|
||||
m_defaultItemShader = createFragmentShaderFromCode("Item", glslMainFragmentShader + glslTextureSrcFragmentShader);
|
||||
setupItemShader(m_defaultItemShader);
|
||||
|
||||
m_defaultMapShader = createFragmentShaderFromCode("Map", glslMainFragmentShader + glslTextureSrcFragmentShader);
|
||||
|
||||
PainterShaderProgram::release();
|
||||
}
|
||||
|
||||
void ShaderManager::terminate()
|
||||
{
|
||||
m_defaultItemShader = nullptr;
|
||||
m_defaultMapShader = nullptr;
|
||||
m_shaders.clear();
|
||||
}
|
||||
|
||||
PainterShaderProgramPtr ShaderManager::createShader(const std::string& name)
|
||||
{
|
||||
if(!g_graphics.canUseShaders()) {
|
||||
g_logger.error(stdext::format("unable to create shader '%s', shaders are not supported", name));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
PainterShaderProgramPtr shader(new PainterShaderProgram);
|
||||
m_shaders[name] = shader;
|
||||
return shader;
|
||||
}
|
||||
|
||||
PainterShaderProgramPtr ShaderManager::createFragmentShader(const std::string& name, const std::string& file)
|
||||
{
|
||||
PainterShaderProgramPtr shader = createShader(name);
|
||||
if(!shader)
|
||||
return nullptr;
|
||||
|
||||
shader->addShaderFromSourceCode(Shader::Vertex, glslMainWithTexCoordsVertexShader + glslPositionOnlyVertexShader);
|
||||
if(!shader->addShaderFromSourceFile(Shader::Fragment, file)) {
|
||||
g_logger.error(stdext::format("unable to load fragment shader '%s' from source file '%s'", name, file));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if(!shader->link()) {
|
||||
g_logger.error(stdext::format("unable to link shader '%s' from file '%s'", name, file));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
m_shaders[name] = shader;
|
||||
return shader;
|
||||
}
|
||||
|
||||
PainterShaderProgramPtr ShaderManager::createFragmentShaderFromCode(const std::string& name, const std::string& code)
|
||||
{
|
||||
PainterShaderProgramPtr shader = createShader(name);
|
||||
if(!shader)
|
||||
return nullptr;
|
||||
|
||||
shader->addShaderFromSourceCode(Shader::Vertex, glslMainWithTexCoordsVertexShader + glslPositionOnlyVertexShader);
|
||||
if(!shader->addShaderFromSourceCode(Shader::Fragment, code)) {
|
||||
g_logger.error(stdext::format("unable to load fragment shader '%s'", name));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if(!shader->link()) {
|
||||
g_logger.error(stdext::format("unable to link shader '%s'", name));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
m_shaders[name] = shader;
|
||||
return shader;
|
||||
}
|
||||
|
||||
PainterShaderProgramPtr ShaderManager::createItemShader(const std::string& name, const std::string& file)
|
||||
{
|
||||
PainterShaderProgramPtr shader = createFragmentShader(name, file);
|
||||
if(shader)
|
||||
setupItemShader(shader);
|
||||
return shader;
|
||||
}
|
||||
|
||||
void ShaderManager::setupItemShader(const PainterShaderProgramPtr& shader)
|
||||
{
|
||||
if(!shader)
|
||||
return;
|
||||
shader->bindUniformLocation(ITEM_ID_UNIFORM, "u_ItemId");
|
||||
}
|
||||
|
||||
PainterShaderProgramPtr ShaderManager::getShader(const std::string& name)
|
||||
{
|
||||
auto it = m_shaders.find(name);
|
||||
if(it != m_shaders.end())
|
||||
return it->second;
|
||||
return nullptr;
|
||||
}
|
||||
63
src/client/shadermanager.h
Normal file
63
src/client/shadermanager.h
Normal file
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright (c) 2010-2013 OTClient <https://github.com/edubart/otclient>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef SHADERMANAGER_H
|
||||
#define SHADERMANAGER_H
|
||||
|
||||
#include "declarations.h"
|
||||
#include <framework/graphics/paintershaderprogram.h>
|
||||
|
||||
//@bindsingleton g_shaders
|
||||
class ShaderManager
|
||||
{
|
||||
public:
|
||||
enum {
|
||||
ITEM_ID_UNIFORM = 10
|
||||
};
|
||||
|
||||
void init();
|
||||
void terminate();
|
||||
|
||||
PainterShaderProgramPtr createShader(const std::string& name);
|
||||
PainterShaderProgramPtr createFragmentShader(const std::string& name, const std::string& file);
|
||||
PainterShaderProgramPtr createFragmentShaderFromCode(const std::string& name, const std::string& code);
|
||||
|
||||
PainterShaderProgramPtr createItemShader(const std::string& name, const std::string& file);
|
||||
PainterShaderProgramPtr createMapShader(const std::string& name, const std::string& file) { return createFragmentShader(name, file); }
|
||||
|
||||
const PainterShaderProgramPtr& getDefaultItemShader() { return m_defaultItemShader; }
|
||||
const PainterShaderProgramPtr& getDefaultMapShader() { return m_defaultMapShader; }
|
||||
|
||||
PainterShaderProgramPtr getShader(const std::string& name);
|
||||
|
||||
private:
|
||||
void setupItemShader(const PainterShaderProgramPtr& shader);
|
||||
|
||||
PainterShaderProgramPtr m_defaultItemShader;
|
||||
PainterShaderProgramPtr m_defaultMapShader;
|
||||
std::unordered_map<std::string, PainterShaderProgramPtr> m_shaders;
|
||||
};
|
||||
|
||||
|
||||
extern ShaderManager g_shaders;
|
||||
|
||||
#endif
|
||||
143
src/client/spritemanager.cpp
Normal file
143
src/client/spritemanager.cpp
Normal file
@@ -0,0 +1,143 @@
|
||||
/*
|
||||
* Copyright (c) 2010-2013 OTClient <https://github.com/edubart/otclient>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "spritemanager.h"
|
||||
#include "game.h"
|
||||
#include <framework/core/resourcemanager.h>
|
||||
#include <framework/core/filestream.h>
|
||||
#include <framework/graphics/image.h>
|
||||
|
||||
SpriteManager g_sprites;
|
||||
|
||||
SpriteManager::SpriteManager()
|
||||
{
|
||||
m_spritesCount = 0;
|
||||
m_signature = 0;
|
||||
}
|
||||
|
||||
void SpriteManager::terminate()
|
||||
{
|
||||
unload();
|
||||
}
|
||||
|
||||
bool SpriteManager::loadSpr(const std::string& file)
|
||||
{
|
||||
m_spritesCount = 0;
|
||||
m_signature = 0;
|
||||
m_loaded = false;
|
||||
try {
|
||||
m_spritesFile = g_resources.openFile(file);
|
||||
// cache file buffer to avoid lags from hard drive
|
||||
m_spritesFile->cache();
|
||||
|
||||
m_signature = m_spritesFile->getU32();
|
||||
m_spritesCount = g_game.getFeature(Otc::GameSpritesU32) ? m_spritesFile->getU32() : m_spritesFile->getU16();
|
||||
m_spritesOffset = m_spritesFile->tell();
|
||||
m_loaded = true;
|
||||
return true;
|
||||
} catch(stdext::exception& e) {
|
||||
g_logger.error(stdext::format("Failed to load sprites from '%s': %s", file, e.what()));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void SpriteManager::unload()
|
||||
{
|
||||
m_spritesCount = 0;
|
||||
m_signature = 0;
|
||||
m_spritesFile = nullptr;
|
||||
}
|
||||
|
||||
ImagePtr SpriteManager::getSpriteImage(int id)
|
||||
{
|
||||
try {
|
||||
enum {
|
||||
SPRITE_SIZE = 32,
|
||||
SPRITE_DATA_SIZE = SPRITE_SIZE*SPRITE_SIZE*4
|
||||
};
|
||||
|
||||
if(id == 0 || !m_spritesFile)
|
||||
return nullptr;
|
||||
|
||||
m_spritesFile->seek(((id-1) * 4) + m_spritesOffset);
|
||||
|
||||
uint32 spriteAddress = m_spritesFile->getU32();
|
||||
|
||||
// no sprite? return an empty texture
|
||||
if(spriteAddress == 0)
|
||||
return nullptr;
|
||||
|
||||
m_spritesFile->seek(spriteAddress);
|
||||
|
||||
// skip color key
|
||||
m_spritesFile->getU8();
|
||||
m_spritesFile->getU8();
|
||||
m_spritesFile->getU8();
|
||||
|
||||
uint16 pixelDataSize = m_spritesFile->getU16();
|
||||
|
||||
ImagePtr image(new Image(Size(SPRITE_SIZE, SPRITE_SIZE)));
|
||||
|
||||
uint8 *pixels = image->getPixelData();
|
||||
int writePos = 0;
|
||||
int read = 0;
|
||||
|
||||
// decompress pixels
|
||||
while(read < pixelDataSize && writePos < SPRITE_DATA_SIZE) {
|
||||
uint16 transparentPixels = m_spritesFile->getU16();
|
||||
uint16 coloredPixels = m_spritesFile->getU16();
|
||||
|
||||
for(int i = 0; i < transparentPixels && writePos < SPRITE_DATA_SIZE; i++) {
|
||||
pixels[writePos + 0] = 0x00;
|
||||
pixels[writePos + 1] = 0x00;
|
||||
pixels[writePos + 2] = 0x00;
|
||||
pixels[writePos + 3] = 0x00;
|
||||
writePos += 4;
|
||||
}
|
||||
|
||||
for(int i = 0; i < coloredPixels && writePos < SPRITE_DATA_SIZE; i++) {
|
||||
pixels[writePos + 0] = m_spritesFile->getU8();
|
||||
pixels[writePos + 1] = m_spritesFile->getU8();
|
||||
pixels[writePos + 2] = m_spritesFile->getU8();
|
||||
pixels[writePos + 3] = 0xFF;
|
||||
writePos += 4;
|
||||
}
|
||||
|
||||
read += 4 + (3 * coloredPixels);
|
||||
}
|
||||
|
||||
// fill remaining pixels with alpha
|
||||
while(writePos < SPRITE_DATA_SIZE) {
|
||||
pixels[writePos + 0] = 0x00;
|
||||
pixels[writePos + 1] = 0x00;
|
||||
pixels[writePos + 2] = 0x00;
|
||||
pixels[writePos + 3] = 0x00;
|
||||
writePos += 4;
|
||||
}
|
||||
|
||||
return image;
|
||||
} catch(stdext::exception& e) {
|
||||
g_logger.error(stdext::format("Failed to get sprite id %d: %s", id, e.what()));
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
56
src/client/spritemanager.h
Normal file
56
src/client/spritemanager.h
Normal file
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright (c) 2010-2013 OTClient <https://github.com/edubart/otclient>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef SPRITEMANAGER_H
|
||||
#define SPRITEMANAGER_H
|
||||
|
||||
#include <framework/core/declarations.h>
|
||||
#include <framework/graphics/declarations.h>
|
||||
|
||||
//@bindsingleton g_sprites
|
||||
class SpriteManager
|
||||
{
|
||||
public:
|
||||
SpriteManager();
|
||||
|
||||
void terminate();
|
||||
|
||||
bool loadSpr(const std::string& file);
|
||||
void unload();
|
||||
|
||||
uint32 getSignature() { return m_signature; }
|
||||
int getSpritesCount() { return m_spritesCount; }
|
||||
|
||||
ImagePtr getSpriteImage(int id);
|
||||
bool isLoaded() { return m_loaded; }
|
||||
|
||||
private:
|
||||
stdext::boolean<false> m_loaded;
|
||||
uint32 m_signature;
|
||||
int m_spritesCount;
|
||||
int m_spritesOffset;
|
||||
FileStreamPtr m_spritesFile;
|
||||
};
|
||||
|
||||
extern SpriteManager g_sprites;
|
||||
|
||||
#endif
|
||||
142
src/client/statictext.cpp
Normal file
142
src/client/statictext.cpp
Normal file
@@ -0,0 +1,142 @@
|
||||
/*
|
||||
* Copyright (c) 2010-2013 OTClient <https://github.com/edubart/otclient>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "statictext.h"
|
||||
#include "map.h"
|
||||
#include <framework/core/clock.h>
|
||||
#include <framework/core/eventdispatcher.h>
|
||||
#include <framework/graphics/graphics.h>
|
||||
#include <framework/graphics/fontmanager.h>
|
||||
|
||||
StaticText::StaticText()
|
||||
{
|
||||
m_cachedText.setFont(g_fonts.getFont("verdana-11px-rounded"));
|
||||
m_cachedText.setAlign(Fw::AlignCenter);
|
||||
}
|
||||
|
||||
void StaticText::drawText(const Point& dest, const Rect& parentRect)
|
||||
{
|
||||
Size textSize = m_cachedText.getTextSize();
|
||||
Rect rect = Rect(dest - Point(textSize.width() / 2, textSize.height()) + Point(20, 5), textSize);
|
||||
Rect boundRect = rect;
|
||||
boundRect.bind(parentRect);
|
||||
|
||||
// draw only if the real center is not too far from the parent center, or its a yell
|
||||
//if(g_map.isAwareOfPosition(m_position) || isYell()) {
|
||||
g_painter->setColor(m_color);
|
||||
m_cachedText.draw(boundRect);
|
||||
//}
|
||||
}
|
||||
|
||||
bool StaticText::addMessage(const std::string& name, Otc::MessageMode mode, const std::string& text)
|
||||
{
|
||||
//TODO: this could be moved to lua
|
||||
// first message
|
||||
if(m_messages.size() == 0) {
|
||||
m_name = name;
|
||||
m_mode = mode;
|
||||
}
|
||||
// check if we can really own the message
|
||||
else if(m_name != name || m_mode != mode) {
|
||||
return false;
|
||||
}
|
||||
// too many messages
|
||||
else if(m_messages.size() > 10) {
|
||||
m_messages.pop_front();
|
||||
m_updateEvent->cancel();
|
||||
m_updateEvent = nullptr;
|
||||
}
|
||||
|
||||
int delay = std::max<int>(Otc::STATIC_DURATION_PER_CHARACTER * text.length(), Otc::MIN_STATIC_TEXT_DURATION);
|
||||
if(isYell())
|
||||
delay *= 2;
|
||||
|
||||
m_messages.push_back(std::make_pair(text, g_clock.millis() + delay));
|
||||
compose();
|
||||
|
||||
if(!m_updateEvent)
|
||||
scheduleUpdate();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void StaticText::update()
|
||||
{
|
||||
m_messages.pop_front();
|
||||
if(m_messages.empty()) {
|
||||
// schedule removal
|
||||
auto self = asStaticText();
|
||||
g_dispatcher.addEvent([self]() { g_map.removeThing(self); });
|
||||
} else {
|
||||
compose();
|
||||
scheduleUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
void StaticText::scheduleUpdate()
|
||||
{
|
||||
int delay = std::max<int>(m_messages.front().second - g_clock.millis(), 0);
|
||||
|
||||
auto self = asStaticText();
|
||||
m_updateEvent = g_dispatcher.scheduleEvent([self]() {
|
||||
self->m_updateEvent = nullptr;
|
||||
self->update();
|
||||
}, delay);
|
||||
}
|
||||
|
||||
void StaticText::compose()
|
||||
{
|
||||
//TODO: this could be moved to lua
|
||||
std::string text;
|
||||
|
||||
if(m_mode == Otc::MessageSay) {
|
||||
text += m_name;
|
||||
text += " says:\n";
|
||||
m_color = Color(239, 239, 0);
|
||||
} else if(m_mode == Otc::MessageWhisper) {
|
||||
text += m_name;
|
||||
text += " whispers:\n";
|
||||
m_color = Color(239, 239, 0);
|
||||
} else if(m_mode == Otc::MessageYell) {
|
||||
text += m_name;
|
||||
text += " yells:\n";
|
||||
m_color = Color(239, 239, 0);
|
||||
} else if(m_mode == Otc::MessageMonsterSay || m_mode == Otc::MessageMonsterYell || m_mode == Otc::MessageSpell || m_mode == Otc::MessageBarkLow || m_mode == Otc::MessageBarkLoud) {
|
||||
m_color = Color(254, 101, 0);
|
||||
} else if(m_mode == Otc::MessageNpcFrom) {
|
||||
text += m_name;
|
||||
text += " says:\n";
|
||||
m_color = Color(95, 247, 247);
|
||||
} else {
|
||||
g_logger.warning(stdext::format("Unknown speak type: %d", m_mode));
|
||||
}
|
||||
|
||||
for(uint i = 0; i < m_messages.size(); ++i) {
|
||||
text += m_messages[i].first;
|
||||
|
||||
if(i < m_messages.size() - 1)
|
||||
text += "\n";
|
||||
}
|
||||
|
||||
m_cachedText.setText(text);
|
||||
m_cachedText.wrapText(275);
|
||||
}
|
||||
63
src/client/statictext.h
Normal file
63
src/client/statictext.h
Normal file
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright (c) 2010-2013 OTClient <https://github.com/edubart/otclient>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef STATICTEXT_H
|
||||
#define STATICTEXT_H
|
||||
|
||||
#include "thing.h"
|
||||
#include <framework/graphics/cachedtext.h>
|
||||
#include <framework/core/timer.h>
|
||||
|
||||
// @bindclass
|
||||
class StaticText : public Thing
|
||||
{
|
||||
public:
|
||||
StaticText();
|
||||
|
||||
void drawText(const Point& dest, const Rect& parentRect);
|
||||
|
||||
std::string getName() { return m_name; }
|
||||
Otc::MessageMode getMessageMode() { return m_mode; }
|
||||
std::string getFirstMessage() { return m_messages[0].first; }
|
||||
|
||||
bool isYell() { return m_mode == Otc::MessageYell || m_mode == Otc::MessageMonsterYell || m_mode == Otc::MessageBarkLoud; }
|
||||
|
||||
bool addMessage(const std::string& name, Otc::MessageMode mode, const std::string& text);
|
||||
|
||||
StaticTextPtr asStaticText() { return static_self_cast<StaticText>(); }
|
||||
bool isStaticText() { return true; }
|
||||
|
||||
private:
|
||||
void update();
|
||||
void scheduleUpdate();
|
||||
void compose();
|
||||
|
||||
stdext::boolean<false> m_yell;
|
||||
std::deque<std::pair<std::string, ticks_t>> m_messages;
|
||||
std::string m_name;
|
||||
Otc::MessageMode m_mode;
|
||||
Color m_color;
|
||||
CachedText m_cachedText;
|
||||
ScheduledEventPtr m_updateEvent;
|
||||
};
|
||||
|
||||
#endif
|
||||
96
src/client/thing.cpp
Normal file
96
src/client/thing.cpp
Normal file
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* Copyright (c) 2010-2013 OTClient <https://github.com/edubart/otclient>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "thing.h"
|
||||
#include "spritemanager.h"
|
||||
#include "thingtypemanager.h"
|
||||
#include <framework/graphics/graphics.h>
|
||||
#include "map.h"
|
||||
#include "tile.h"
|
||||
#include "game.h"
|
||||
|
||||
Thing::Thing() :
|
||||
m_datId(0)
|
||||
{
|
||||
}
|
||||
|
||||
void Thing::setPosition(const Position& position)
|
||||
{
|
||||
if(m_position == position)
|
||||
return;
|
||||
|
||||
Position oldPos = m_position;
|
||||
m_position = position;
|
||||
onPositionChange(position, oldPos);
|
||||
}
|
||||
|
||||
int Thing::getStackPriority()
|
||||
{
|
||||
if(isGround())
|
||||
return 0;
|
||||
else if(isGroundBorder())
|
||||
return 1;
|
||||
else if(isOnBottom())
|
||||
return 2;
|
||||
else if(isOnTop())
|
||||
return 3;
|
||||
else if(isCreature())
|
||||
return 4;
|
||||
else // common items
|
||||
return 5;
|
||||
}
|
||||
|
||||
const TilePtr& Thing::getTile()
|
||||
{
|
||||
return g_map.getTile(m_position);
|
||||
}
|
||||
|
||||
ContainerPtr Thing::getParentContainer()
|
||||
{
|
||||
if(m_position.x == 0xffff && m_position.y & 0x40) {
|
||||
int containerId = m_position.y ^ 0x40;
|
||||
return g_game.getContainer(containerId);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
int Thing::getStackpos()
|
||||
{
|
||||
if(m_position.x == 65535 && isItem()) // is inside a container
|
||||
return m_position.z;
|
||||
else if(const TilePtr& tile = getTile())
|
||||
return tile->getThingStackpos(static_self_cast<Thing>());
|
||||
else {
|
||||
g_logger.traceError("got a thing with invalid stackpos");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
const ThingTypePtr& Thing::getThingType()
|
||||
{
|
||||
return g_things.getNullThingType();
|
||||
}
|
||||
|
||||
ThingType* Thing::rawGetThingType()
|
||||
{
|
||||
return g_things.getNullThingType().get();
|
||||
}
|
||||
132
src/client/thing.h
Normal file
132
src/client/thing.h
Normal file
@@ -0,0 +1,132 @@
|
||||
/*
|
||||
* Copyright (c) 2010-2013 OTClient <https://github.com/edubart/otclient>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef THING_H
|
||||
#define THING_H
|
||||
|
||||
#include "declarations.h"
|
||||
#include "thingtype.h"
|
||||
#include "thingtypemanager.h"
|
||||
#include <framework/luaengine/luaobject.h>
|
||||
|
||||
// @bindclass
|
||||
#pragma pack(push,1) // disable memory alignment
|
||||
class Thing : public LuaObject
|
||||
{
|
||||
public:
|
||||
Thing();
|
||||
virtual ~Thing() { }
|
||||
|
||||
virtual void draw(const Point& dest, float scaleFactor, bool animate, LightView *lightView = nullptr) { }
|
||||
|
||||
virtual void setId(uint32 id) { }
|
||||
void setPosition(const Position& position);
|
||||
|
||||
virtual uint32 getId() { return 0; }
|
||||
Position getPosition() { return m_position; }
|
||||
int getStackPriority();
|
||||
const TilePtr& getTile();
|
||||
ContainerPtr getParentContainer();
|
||||
int getStackpos();
|
||||
|
||||
virtual bool isItem() { return false; }
|
||||
virtual bool isEffect() { return false; }
|
||||
virtual bool isMissile() { return false; }
|
||||
virtual bool isCreature() { return false; }
|
||||
virtual bool isNpc() { return false; }
|
||||
virtual bool isMonster() { return false; }
|
||||
virtual bool isPlayer() { return false; }
|
||||
virtual bool isLocalPlayer() { return false; }
|
||||
virtual bool isAnimatedText() { return false; }
|
||||
virtual bool isStaticText() { return false; }
|
||||
|
||||
// type shortcuts
|
||||
virtual const ThingTypePtr& getThingType();
|
||||
virtual ThingType *rawGetThingType();
|
||||
Size getSize() { return rawGetThingType()->getSize(); }
|
||||
int getWidth() { return rawGetThingType()->getWidth(); }
|
||||
int getHeight() { return rawGetThingType()->getHeight(); }
|
||||
virtual Point getDisplacement() { return rawGetThingType()->getDisplacement(); }
|
||||
virtual int getDisplacementX() { return rawGetThingType()->getDisplacementX(); }
|
||||
virtual int getDisplacementY() { return rawGetThingType()->getDisplacementY(); }
|
||||
virtual int getExactSize(int layer, int xPattern, int yPattern, int zPattern, int animationPhase) { return rawGetThingType()->getExactSize(layer, xPattern, yPattern, zPattern, animationPhase); }
|
||||
int getLayers() { return rawGetThingType()->getLayers(); }
|
||||
int getNumPatternX() { return rawGetThingType()->getNumPatternX(); }
|
||||
int getNumPatternY() { return rawGetThingType()->getNumPatternY(); }
|
||||
int getNumPatternZ() { return rawGetThingType()->getNumPatternZ(); }
|
||||
int getAnimationPhases() { return rawGetThingType()->getAnimationPhases(); }
|
||||
int getGroundSpeed() { return rawGetThingType()->getGroundSpeed(); }
|
||||
int getMaxTextLength() { return rawGetThingType()->getMaxTextLength(); }
|
||||
Light getLight() { return rawGetThingType()->getLight(); }
|
||||
int getMinimapColor() { return rawGetThingType()->getMinimapColor(); }
|
||||
int getLensHelp() { return rawGetThingType()->getLensHelp(); }
|
||||
int getClothSlot() { return rawGetThingType()->getClothSlot(); }
|
||||
int getElevation() { return rawGetThingType()->getElevation(); }
|
||||
bool isGround() { return rawGetThingType()->isGround(); }
|
||||
bool isGroundBorder() { return rawGetThingType()->isGroundBorder(); }
|
||||
bool isOnBottom() { return rawGetThingType()->isOnBottom(); }
|
||||
bool isOnTop() { return rawGetThingType()->isOnTop(); }
|
||||
bool isContainer() { return rawGetThingType()->isContainer(); }
|
||||
bool isStackable() { return rawGetThingType()->isStackable(); }
|
||||
bool isForceUse() { return rawGetThingType()->isForceUse(); }
|
||||
bool isMultiUse() { return rawGetThingType()->isMultiUse(); }
|
||||
bool isWritable() { return rawGetThingType()->isWritable(); }
|
||||
bool isChargeable() { return rawGetThingType()->isChargeable(); }
|
||||
bool isWritableOnce() { return rawGetThingType()->isWritableOnce(); }
|
||||
bool isFluidContainer() { return rawGetThingType()->isFluidContainer(); }
|
||||
bool isSplash() { return rawGetThingType()->isSplash(); }
|
||||
bool isNotWalkable() { return rawGetThingType()->isNotWalkable(); }
|
||||
bool isNotMoveable() { return rawGetThingType()->isNotMoveable(); }
|
||||
bool blockProjectile() { return rawGetThingType()->blockProjectile(); }
|
||||
bool isNotPathable() { return rawGetThingType()->isNotPathable(); }
|
||||
bool isPickupable() { return rawGetThingType()->isPickupable(); }
|
||||
bool isHangable() { return rawGetThingType()->isHangable(); }
|
||||
bool isHookSouth() { return rawGetThingType()->isHookSouth(); }
|
||||
bool isHookEast() { return rawGetThingType()->isHookEast(); }
|
||||
bool isRotateable() { return rawGetThingType()->isRotateable(); }
|
||||
bool hasLight() { return rawGetThingType()->hasLight(); }
|
||||
bool isDontHide() { return rawGetThingType()->isDontHide(); }
|
||||
bool isTranslucent() { return rawGetThingType()->isTranslucent(); }
|
||||
bool hasDisplacement() { return rawGetThingType()->hasDisplacement(); }
|
||||
bool hasElevation() { return rawGetThingType()->hasElevation(); }
|
||||
bool isLyingCorpse() { return rawGetThingType()->isLyingCorpse(); }
|
||||
bool isAnimateAlways() { return rawGetThingType()->isAnimateAlways(); }
|
||||
bool hasMiniMapColor() { return rawGetThingType()->hasMiniMapColor(); }
|
||||
bool hasLensHelp() { return rawGetThingType()->hasLensHelp(); }
|
||||
bool isFullGround() { return rawGetThingType()->isFullGround(); }
|
||||
bool isIgnoreLook() { return rawGetThingType()->isIgnoreLook(); }
|
||||
bool isCloth() { return rawGetThingType()->isCloth(); }
|
||||
bool isMarketable() { return rawGetThingType()->isMarketable(); }
|
||||
MarketData getMarketData() { return rawGetThingType()->getMarketData(); }
|
||||
|
||||
virtual void onPositionChange(const Position& newPos, const Position& oldPos) { }
|
||||
virtual void onAppear() { }
|
||||
virtual void onDisappear() { }
|
||||
|
||||
protected:
|
||||
Position m_position;
|
||||
uint16 m_datId;
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
#endif
|
||||
|
||||
67
src/client/thingstype.h
Normal file
67
src/client/thingstype.h
Normal file
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Copyright (c) 2010-2013 OTClient <https://github.com/edubart/otclient>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef DATMANAGER_H
|
||||
#define DATMANAGER_H
|
||||
|
||||
#include <framework/global.h>
|
||||
#include <framework/core/declarations.h>
|
||||
#include "thingtype.h"
|
||||
|
||||
//@bindsingleton g_thingsType
|
||||
class ThingsType
|
||||
{
|
||||
public:
|
||||
|
||||
enum Categories {
|
||||
Item = 0,
|
||||
Creature,
|
||||
Effect,
|
||||
Missile,
|
||||
LastCategory
|
||||
};
|
||||
|
||||
bool load(const std::string& file);
|
||||
void unload();
|
||||
|
||||
bool parseThingType(const FileStreamPtr& fin, ThingType& thingType);
|
||||
|
||||
ThingType *getEmptyThingType() { return &m_emptyThingType; }
|
||||
ThingType *getThingType(uint16 id, Categories category);
|
||||
|
||||
uint32 getSignature() { return m_signature; }
|
||||
bool isLoaded() { return m_loaded; }
|
||||
|
||||
uint16 getFirstItemId() { return 100; }
|
||||
uint16 getMaxItemid() { return m_things[Item].size() + 99; }
|
||||
bool isValidItemId(int id) { return id >= getFirstItemId() && id <= getMaxItemid(); }
|
||||
|
||||
private:
|
||||
uint32 m_signature;
|
||||
stdext::boolean<false> m_loaded;
|
||||
ThingTypeList m_things[LastCategory];
|
||||
static ThingType m_emptyThingType;
|
||||
};
|
||||
|
||||
extern ThingsType g_thingsType;
|
||||
|
||||
#endif
|
||||
304
src/client/thingtype.cpp
Normal file
304
src/client/thingtype.cpp
Normal file
@@ -0,0 +1,304 @@
|
||||
/*
|
||||
* Copyright (c) 2010-2013 OTClient <https://github.com/edubart/otclient>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "thingtype.h"
|
||||
#include "spritemanager.h"
|
||||
#include "game.h"
|
||||
#include "lightview.h"
|
||||
|
||||
#include <framework/graphics/graphics.h>
|
||||
#include <framework/graphics/texture.h>
|
||||
#include <framework/graphics/image.h>
|
||||
#include <framework/graphics/texturemanager.h>
|
||||
#include <framework/core/filestream.h>
|
||||
|
||||
ThingType::ThingType()
|
||||
{
|
||||
m_category = ThingInvalidCategory;
|
||||
m_id = 0;
|
||||
m_null = true;
|
||||
m_exactSize = 0;
|
||||
m_numPatternX = m_numPatternY = m_numPatternZ = 0;
|
||||
m_animationPhases = 0;
|
||||
m_layers = 0;
|
||||
m_elevation = 0;
|
||||
}
|
||||
|
||||
void ThingType::unserialize(uint16 clientId, ThingCategory category, const FileStreamPtr& fin)
|
||||
{
|
||||
m_null = false;
|
||||
m_id = clientId;
|
||||
m_category = category;
|
||||
|
||||
bool done = false;
|
||||
for(int i = 0 ; i < ThingLastAttr;++i) {
|
||||
int attr = fin->getU8();
|
||||
if(attr == ThingLastAttr) {
|
||||
done = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if(g_game.getFeature(Otc::GameChargeableItems)) {
|
||||
if(attr == ThingAttrWritable) {
|
||||
m_attribs.set(ThingAttrChargeable, true);
|
||||
continue;
|
||||
} else if(attr > ThingAttrWritable)
|
||||
attr -= 1;
|
||||
}
|
||||
|
||||
switch(attr) {
|
||||
case ThingAttrDisplacement: {
|
||||
m_displacement.x = fin->getU16();
|
||||
m_displacement.y = fin->getU16();
|
||||
m_attribs.set(attr, true);
|
||||
break;
|
||||
}
|
||||
case ThingAttrLight: {
|
||||
Light light;
|
||||
light.intensity = fin->getU16();
|
||||
light.color = fin->getU16();
|
||||
m_attribs.set(attr, light);
|
||||
break;
|
||||
}
|
||||
case ThingAttrMarket: {
|
||||
MarketData market;
|
||||
market.category = fin->getU16();
|
||||
market.tradeAs = fin->getU16();
|
||||
market.showAs = fin->getU16();
|
||||
market.name = fin->getString();
|
||||
market.restrictVocation = fin->getU16();
|
||||
market.requiredLevel = fin->getU16();
|
||||
m_attribs.set(attr, market);
|
||||
break;
|
||||
}
|
||||
case ThingAttrElevation: {
|
||||
m_elevation = fin->getU16();
|
||||
m_attribs.set(attr, m_elevation);
|
||||
break;
|
||||
}
|
||||
case ThingAttrGround:
|
||||
case ThingAttrWritable:
|
||||
case ThingAttrWritableOnce:
|
||||
case ThingAttrMinimapColor:
|
||||
case ThingAttrCloth:
|
||||
case ThingAttrLensHelp:
|
||||
m_attribs.set(attr, fin->getU16());
|
||||
break;
|
||||
default:
|
||||
m_attribs.set(attr, true);
|
||||
break;
|
||||
};
|
||||
}
|
||||
|
||||
if(!done)
|
||||
stdext::throw_exception("corrupt data");
|
||||
|
||||
uint8 width = fin->getU8();
|
||||
uint8 height = fin->getU8();
|
||||
m_size = Size(width, height);
|
||||
m_exactSize = (width > 1 || height > 1) ? std::min((int)fin->getU8(), std::max(width * 32, height * 32)) : 32;
|
||||
m_layers = fin->getU8();
|
||||
m_numPatternX = fin->getU8();
|
||||
m_numPatternY = fin->getU8();
|
||||
m_numPatternZ = fin->getU8();
|
||||
m_animationPhases = fin->getU8();
|
||||
|
||||
int totalSprites = m_size.area() * m_layers * m_numPatternX * m_numPatternY * m_numPatternZ * m_animationPhases;
|
||||
|
||||
if(totalSprites == 0)
|
||||
stdext::throw_exception("a thing type has no sprites");
|
||||
if(totalSprites > 4096)
|
||||
stdext::throw_exception("a thing type has more than 4096 sprites");
|
||||
|
||||
m_spritesIndex.resize(totalSprites);
|
||||
for(int i = 0; i < totalSprites; i++)
|
||||
m_spritesIndex[i] = g_game.getFeature(Otc::GameSpritesU32) ? fin->getU32() : fin->getU16();
|
||||
|
||||
m_textures.resize(m_animationPhases);
|
||||
m_texturesFramesRects.resize(m_animationPhases);
|
||||
m_texturesFramesOriginRects.resize(m_animationPhases);
|
||||
m_texturesFramesOffsets.resize(m_animationPhases);
|
||||
}
|
||||
|
||||
void ThingType::draw(const Point& dest, float scaleFactor, int layer, int xPattern, int yPattern, int zPattern, int animationPhase, LightView *lightView)
|
||||
{
|
||||
if(m_null)
|
||||
return;
|
||||
|
||||
const TexturePtr& texture = getTexture(animationPhase); // texture might not exists, neither its rects.
|
||||
|
||||
int frameIndex = getTextureIndex(layer, xPattern, yPattern, zPattern);
|
||||
Point textureOffset;
|
||||
Rect textureRect;
|
||||
|
||||
if(scaleFactor != 1.0f) {
|
||||
textureRect = m_texturesFramesOriginRects[animationPhase][frameIndex];
|
||||
} else {
|
||||
textureOffset = m_texturesFramesOffsets[animationPhase][frameIndex];
|
||||
textureRect = m_texturesFramesRects[animationPhase][frameIndex];
|
||||
}
|
||||
|
||||
Rect screenRect(dest + (textureOffset - m_displacement - (m_size.toPoint() - Point(1, 1)) * 32) * scaleFactor,
|
||||
textureRect.size() * scaleFactor);
|
||||
|
||||
g_painter->drawTexturedRect(screenRect, texture, textureRect);
|
||||
|
||||
if(lightView && hasLight()) {
|
||||
Light light = getLight();
|
||||
if(light.intensity > 0)
|
||||
lightView->addLightSource(screenRect.center(), scaleFactor, light);
|
||||
}
|
||||
}
|
||||
|
||||
const TexturePtr& ThingType::getTexture(int animationPhase)
|
||||
{
|
||||
TexturePtr& animationPhaseTexture = m_textures[animationPhase];
|
||||
if(!animationPhaseTexture) {
|
||||
// we don't need layers in common items, they will be pre-drawn
|
||||
int textureLayers = 1;
|
||||
int numLayers = m_layers;
|
||||
if(m_category == ThingCategoryCreature && numLayers >= 2) {
|
||||
// 5 layers: outfit base, red mask, green mask, blue mask, yellow mask
|
||||
textureLayers = 5;
|
||||
numLayers = 5;
|
||||
}
|
||||
|
||||
int indexSize = textureLayers * m_numPatternX * m_numPatternY * m_numPatternZ;
|
||||
Size textureSize = getBestTextureDimension(m_size.width(), m_size.height(), indexSize);
|
||||
ImagePtr fullImage = ImagePtr(new Image(textureSize * Otc::TILE_PIXELS));
|
||||
|
||||
m_texturesFramesRects[animationPhase].resize(indexSize);
|
||||
m_texturesFramesOriginRects[animationPhase].resize(indexSize);
|
||||
m_texturesFramesOffsets[animationPhase].resize(indexSize);
|
||||
|
||||
for(int z = 0; z < m_numPatternZ; ++z) {
|
||||
for(int y = 0; y < m_numPatternY; ++y) {
|
||||
for(int x = 0; x < m_numPatternX; ++x) {
|
||||
for(int l = 0; l < numLayers; ++l) {
|
||||
bool spriteMask = (m_category == ThingCategoryCreature && l > 0);
|
||||
int frameIndex = getTextureIndex(l % textureLayers, x, y, z);
|
||||
Point framePos = Point(frameIndex % (textureSize.width() / m_size.width()) * m_size.width(),
|
||||
frameIndex / (textureSize.width() / m_size.width()) * m_size.height()) * Otc::TILE_PIXELS;
|
||||
|
||||
for(int h = 0; h < m_size.height(); ++h) {
|
||||
for(int w = 0; w < m_size.width(); ++w) {
|
||||
uint spriteIndex = getSpriteIndex(w, h, spriteMask ? 1 : l, x, y, z, animationPhase);
|
||||
ImagePtr spriteImage = g_sprites.getSpriteImage(m_spritesIndex[spriteIndex]);
|
||||
if(spriteImage) {
|
||||
if(spriteMask) {
|
||||
static Color maskColors[] = { Color::red, Color::green, Color::blue, Color::yellow };
|
||||
spriteImage->overwriteMask(maskColors[l - 1]);
|
||||
}
|
||||
Point spritePos = Point(m_size.width() - w - 1,
|
||||
m_size.height() - h - 1) * Otc::TILE_PIXELS;
|
||||
|
||||
fullImage->blit(framePos + spritePos, spriteImage);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Rect drawRect(framePos + Point(m_size.width(), m_size.height()) * Otc::TILE_PIXELS - Point(1,1), framePos);
|
||||
for(int x = framePos.x; x < framePos.x + m_size.width() * Otc::TILE_PIXELS; ++x) {
|
||||
for(int y = framePos.y; y < framePos.y + m_size.height() * Otc::TILE_PIXELS; ++y) {
|
||||
uint8 *p = fullImage->getPixel(x,y);
|
||||
if(p[3] != 0x00) {
|
||||
drawRect.setTop (std::min(y, (int)drawRect.top()));
|
||||
drawRect.setLeft (std::min(x, (int)drawRect.left()));
|
||||
drawRect.setBottom(std::max(y, (int)drawRect.bottom()));
|
||||
drawRect.setRight (std::max(x, (int)drawRect.right()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_texturesFramesRects[animationPhase][frameIndex] = drawRect;
|
||||
m_texturesFramesOriginRects[animationPhase][frameIndex] = Rect(framePos, Size(m_size.width(), m_size.height()) * Otc::TILE_PIXELS);
|
||||
m_texturesFramesOffsets[animationPhase][frameIndex] = drawRect.topLeft() - framePos;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
animationPhaseTexture = TexturePtr(new Texture(fullImage, true));
|
||||
animationPhaseTexture->setSmooth(true);
|
||||
}
|
||||
return animationPhaseTexture;
|
||||
}
|
||||
|
||||
Size ThingType::getBestTextureDimension(int w, int h, int count)
|
||||
{
|
||||
const int MAX = 32;
|
||||
|
||||
int k = 1;
|
||||
while(k < w)
|
||||
k<<=1;
|
||||
w = k;
|
||||
|
||||
k = 1;
|
||||
while(k < h)
|
||||
k<<=1;
|
||||
h = k;
|
||||
|
||||
int numSprites = w*h*count;
|
||||
assert(numSprites <= MAX*MAX);
|
||||
assert(w <= MAX);
|
||||
assert(h <= MAX);
|
||||
|
||||
Size bestDimension = Size(MAX, MAX);
|
||||
for(int i=w;i<=MAX;i<<=1) {
|
||||
for(int j=h;j<=MAX;j<<=1) {
|
||||
Size candidateDimension = Size(i, j);
|
||||
if(candidateDimension.area() < numSprites)
|
||||
continue;
|
||||
if((candidateDimension.area() < bestDimension.area()) ||
|
||||
(candidateDimension.area() == bestDimension.area() && candidateDimension.width() + candidateDimension.height() < bestDimension.width() + bestDimension.height()))
|
||||
bestDimension = candidateDimension;
|
||||
}
|
||||
}
|
||||
|
||||
return bestDimension;
|
||||
}
|
||||
|
||||
uint ThingType::getSpriteIndex(int w, int h, int l, int x, int y, int z, int a) {
|
||||
uint index =
|
||||
((((((a % m_animationPhases)
|
||||
* m_numPatternZ + z)
|
||||
* m_numPatternY + y)
|
||||
* m_numPatternX + x)
|
||||
* m_layers + l)
|
||||
* m_size.height() + h)
|
||||
* m_size.width() + w;
|
||||
assert(index < m_spritesIndex.size());
|
||||
return index;
|
||||
}
|
||||
|
||||
uint ThingType::getTextureIndex(int l, int x, int y, int z) {
|
||||
return ((l * m_numPatternZ + z)
|
||||
* m_numPatternY + y)
|
||||
* m_numPatternX + x;
|
||||
}
|
||||
|
||||
int ThingType::getExactSize(int layer, int xPattern, int yPattern, int zPattern, int animationPhase)
|
||||
{
|
||||
getTexture(animationPhase); // we must calculate it anyway.
|
||||
int frameIndex = getTextureIndex(layer, xPattern, yPattern, zPattern);
|
||||
Size size = m_texturesFramesOriginRects[animationPhase][frameIndex].size() - m_texturesFramesOffsets[animationPhase][frameIndex].toSize();
|
||||
return std::max(size.width(), size.height());
|
||||
}
|
||||
201
src/client/thingtype.h
Normal file
201
src/client/thingtype.h
Normal file
@@ -0,0 +1,201 @@
|
||||
/*
|
||||
* Copyright (c) 2010-2013 OTClient <https://github.com/edubart/otclient>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef THINGTYPE_H
|
||||
#define THINGTYPE_H
|
||||
|
||||
#include "declarations.h"
|
||||
|
||||
#include <framework/core/declarations.h>
|
||||
#include <framework/graphics/texture.h>
|
||||
#include <framework/graphics/coordsbuffer.h>
|
||||
#include <framework/luaengine/luaobject.h>
|
||||
#include <framework/net/server.h>
|
||||
|
||||
enum ThingCategory : uint8 {
|
||||
ThingCategoryItem = 0,
|
||||
ThingCategoryCreature,
|
||||
ThingCategoryEffect,
|
||||
ThingCategoryMissile,
|
||||
ThingInvalidCategory,
|
||||
ThingLastCategory = ThingInvalidCategory
|
||||
};
|
||||
|
||||
enum ThingAttr : uint8 {
|
||||
ThingAttrGround = 0,
|
||||
ThingAttrGroundBorder = 1,
|
||||
ThingAttrOnBottom = 2,
|
||||
ThingAttrOnTop = 3,
|
||||
ThingAttrContainer = 4,
|
||||
ThingAttrStackable = 5,
|
||||
ThingAttrForceUse = 6,
|
||||
ThingAttrMultiUse = 7,
|
||||
ThingAttrWritable = 8,
|
||||
ThingAttrWritableOnce = 9,
|
||||
ThingAttrFluidContainer = 10,
|
||||
ThingAttrSplash = 11,
|
||||
ThingAttrNotWalkable = 12,
|
||||
ThingAttrNotMoveable = 13,
|
||||
ThingAttrBlockProjectile = 14,
|
||||
ThingAttrNotPathable = 15,
|
||||
ThingAttrPickupable = 16,
|
||||
ThingAttrHangable = 17,
|
||||
ThingAttrHookSouth = 18,
|
||||
ThingAttrHookEast = 19,
|
||||
ThingAttrRotateable = 20,
|
||||
ThingAttrLight = 21,
|
||||
ThingAttrDontHide = 22,
|
||||
ThingAttrTranslucent = 23,
|
||||
ThingAttrDisplacement = 24,
|
||||
ThingAttrElevation = 25,
|
||||
ThingAttrLyingCorpse = 26,
|
||||
ThingAttrAnimateAlways = 27,
|
||||
ThingAttrMinimapColor = 28,
|
||||
ThingAttrLensHelp = 29,
|
||||
ThingAttrFullGround = 30,
|
||||
ThingAttrLook = 31,
|
||||
ThingAttrCloth = 32,
|
||||
ThingAttrMarket = 33,
|
||||
ThingAttrChargeable = 254, // deprecated
|
||||
ThingLastAttr = 255
|
||||
};
|
||||
|
||||
enum SpriteMask {
|
||||
SpriteMaskRed = 1,
|
||||
SpriteMaskGreen,
|
||||
SpriteMaskBlue,
|
||||
SpriteMaskYellow
|
||||
};
|
||||
|
||||
struct MarketData {
|
||||
std::string name;
|
||||
int category;
|
||||
uint16 requiredLevel;
|
||||
uint16 restrictVocation;
|
||||
uint16 showAs;
|
||||
uint16 tradeAs;
|
||||
};
|
||||
|
||||
struct Light {
|
||||
Light() { intensity = 0; color = 215; }
|
||||
uint8 intensity;
|
||||
uint8 color;
|
||||
};
|
||||
|
||||
class ThingType : public LuaObject
|
||||
{
|
||||
public:
|
||||
ThingType();
|
||||
|
||||
void unserialize(uint16 clientId, ThingCategory category, const FileStreamPtr& fin);
|
||||
|
||||
void draw(const Point& dest, float scaleFactor, int layer, int xPattern, int yPattern, int zPattern, int animationPhase, LightView *lightView = nullptr);
|
||||
|
||||
uint16 getId() { return m_id; }
|
||||
ThingCategory getCategory() { return m_category; }
|
||||
bool isNull() { return m_null; }
|
||||
bool hasAttr(ThingAttr attr) { return m_attribs.has(attr); }
|
||||
|
||||
Size getSize() { return m_size; }
|
||||
int getWidth() { return m_size.width(); }
|
||||
int getHeight() { return m_size.height(); }
|
||||
int getExactSize(int layer = 0, int xPattern = 0, int yPattern = 0, int zPattern = 0, int animationPhase = 0);
|
||||
int getLayers() { return m_layers; }
|
||||
int getNumPatternX() { return m_numPatternX; }
|
||||
int getNumPatternY() { return m_numPatternY; }
|
||||
int getNumPatternZ() { return m_numPatternZ; }
|
||||
int getAnimationPhases() { return m_animationPhases; }
|
||||
Point getDisplacement() { return m_displacement; }
|
||||
int getDisplacementX() { return getDisplacement().x; }
|
||||
int getDisplacementY() { return getDisplacement().y; }
|
||||
int getElevation() { return m_elevation; }
|
||||
|
||||
int getGroundSpeed() { return m_attribs.get<uint16>(ThingAttrGround); }
|
||||
int getMaxTextLength() { return m_attribs.has(ThingAttrWritableOnce) ? m_attribs.get<uint16>(ThingAttrWritableOnce) : m_attribs.get<uint16>(ThingAttrWritable); }
|
||||
Light getLight() { return m_attribs.get<Light>(ThingAttrLight); }
|
||||
int getMinimapColor() { return m_attribs.get<uint16>(ThingAttrMinimapColor); }
|
||||
int getLensHelp() { return m_attribs.get<uint16>(ThingAttrLensHelp); }
|
||||
int getClothSlot() { return m_attribs.get<uint16>(ThingAttrCloth); }
|
||||
MarketData getMarketData() { return m_attribs.get<MarketData>(ThingAttrMarket); }
|
||||
bool isGround() { return m_attribs.has(ThingAttrGround); }
|
||||
bool isGroundBorder() { return m_attribs.has(ThingAttrGroundBorder); }
|
||||
bool isOnBottom() { return m_attribs.has(ThingAttrOnBottom); }
|
||||
bool isOnTop() { return m_attribs.has(ThingAttrOnTop); }
|
||||
bool isContainer() { return m_attribs.has(ThingAttrContainer); }
|
||||
bool isStackable() { return m_attribs.has(ThingAttrStackable); }
|
||||
bool isForceUse() { return m_attribs.has(ThingAttrForceUse); }
|
||||
bool isMultiUse() { return m_attribs.has(ThingAttrMultiUse); }
|
||||
bool isWritable() { return m_attribs.has(ThingAttrWritable); }
|
||||
bool isChargeable() { return m_attribs.has(ThingAttrChargeable); }
|
||||
bool isWritableOnce() { return m_attribs.has(ThingAttrWritableOnce); }
|
||||
bool isFluidContainer() { return m_attribs.has(ThingAttrFluidContainer); }
|
||||
bool isSplash() { return m_attribs.has(ThingAttrSplash); }
|
||||
bool isNotWalkable() { return m_attribs.has(ThingAttrNotWalkable); }
|
||||
bool isNotMoveable() { return m_attribs.has(ThingAttrNotMoveable); }
|
||||
bool blockProjectile() { return m_attribs.has(ThingAttrBlockProjectile); }
|
||||
bool isNotPathable() { return m_attribs.has(ThingAttrNotPathable); }
|
||||
bool isPickupable() { return m_attribs.has(ThingAttrPickupable); }
|
||||
bool isHangable() { return m_attribs.has(ThingAttrHangable); }
|
||||
bool isHookSouth() { return m_attribs.has(ThingAttrHookSouth); }
|
||||
bool isHookEast() { return m_attribs.has(ThingAttrHookEast); }
|
||||
bool isRotateable() { return m_attribs.has(ThingAttrRotateable); }
|
||||
bool hasLight() { return m_attribs.has(ThingAttrLight); }
|
||||
bool isDontHide() { return m_attribs.has(ThingAttrDontHide); }
|
||||
bool isTranslucent() { return m_attribs.has(ThingAttrTranslucent); }
|
||||
bool hasDisplacement() { return m_attribs.has(ThingAttrDisplacement); }
|
||||
bool hasElevation() { return m_attribs.has(ThingAttrElevation); }
|
||||
bool isLyingCorpse() { return m_attribs.has(ThingAttrLyingCorpse); }
|
||||
bool isAnimateAlways() { return m_attribs.has(ThingAttrAnimateAlways); }
|
||||
bool hasMiniMapColor() { return m_attribs.has(ThingAttrMinimapColor); }
|
||||
bool hasLensHelp() { return m_attribs.has(ThingAttrLensHelp); }
|
||||
bool isFullGround() { return m_attribs.has(ThingAttrFullGround); }
|
||||
bool isIgnoreLook() { return m_attribs.has(ThingAttrLook); }
|
||||
bool isCloth() { return m_attribs.has(ThingAttrCloth); }
|
||||
bool isMarketable() { return m_attribs.has(ThingAttrMarket); }
|
||||
|
||||
private:
|
||||
const TexturePtr& getTexture(int animationPhase);
|
||||
Size getBestTextureDimension(int w, int h, int count);
|
||||
uint getSpriteIndex(int w, int h, int l, int x, int y, int z, int a);
|
||||
uint getTextureIndex(int l, int x, int y, int z);
|
||||
|
||||
ThingCategory m_category;
|
||||
uint16 m_id;
|
||||
bool m_null;
|
||||
stdext::dynamic_storage<uint8> m_attribs;
|
||||
|
||||
Size m_size;
|
||||
Point m_displacement;
|
||||
int m_exactSize;
|
||||
int m_numPatternX, m_numPatternY, m_numPatternZ;
|
||||
int m_animationPhases;
|
||||
int m_layers;
|
||||
int m_elevation;
|
||||
|
||||
std::vector<int> m_spritesIndex;
|
||||
std::vector<TexturePtr> m_textures;
|
||||
std::vector<std::vector<Rect>> m_texturesFramesRects;
|
||||
std::vector<std::vector<Rect>> m_texturesFramesOriginRects;
|
||||
std::vector<std::vector<Point>> m_texturesFramesOffsets;
|
||||
};
|
||||
|
||||
#endif
|
||||
291
src/client/thingtypemanager.cpp
Normal file
291
src/client/thingtypemanager.cpp
Normal file
@@ -0,0 +1,291 @@
|
||||
/*
|
||||
* Copyright (c) 2010-2013 OTClient <https://github.com/edubart/otclient>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "thingtypemanager.h"
|
||||
#include "spritemanager.h"
|
||||
#include "thing.h"
|
||||
#include "thingtype.h"
|
||||
#include "itemtype.h"
|
||||
#include "creature.h"
|
||||
#include "creatures.h"
|
||||
|
||||
#include <framework/core/resourcemanager.h>
|
||||
#include <framework/core/filestream.h>
|
||||
#include <framework/core/binarytree.h>
|
||||
#include <framework/xml/tinyxml.h>
|
||||
|
||||
ThingTypeManager g_things;
|
||||
|
||||
void ThingTypeManager::init()
|
||||
{
|
||||
m_nullThingType = ThingTypePtr(new ThingType);
|
||||
m_nullItemType = ItemTypePtr(new ItemType);
|
||||
m_datSignature = 0;
|
||||
m_otbMinorVersion = 0;
|
||||
m_otbMajorVersion = 0;
|
||||
m_datLoaded = false;
|
||||
m_xmlLoaded = false;
|
||||
m_otbLoaded = false;
|
||||
for(int i = 0; i < ThingLastCategory; ++i)
|
||||
m_thingTypes[i].resize(1, m_nullThingType);
|
||||
m_itemTypes.resize(1, m_nullItemType);
|
||||
}
|
||||
|
||||
void ThingTypeManager::terminate()
|
||||
{
|
||||
for(int i = 0; i < ThingLastCategory; ++i)
|
||||
m_thingTypes[i].clear();
|
||||
m_itemTypes.clear();
|
||||
m_reverseItemTypes.clear();
|
||||
m_nullThingType = nullptr;
|
||||
m_nullItemType = nullptr;
|
||||
}
|
||||
|
||||
bool ThingTypeManager::loadDat(const std::string& file)
|
||||
{
|
||||
m_datLoaded = false;
|
||||
m_datSignature = 0;
|
||||
try {
|
||||
FileStreamPtr fin = g_resources.openFile(file);
|
||||
|
||||
m_datSignature = fin->getU32();
|
||||
|
||||
int numThings[ThingLastCategory];
|
||||
for(int category = 0; category < ThingLastCategory; ++category) {
|
||||
int count = fin->getU16() + 1;
|
||||
m_thingTypes[category].clear();
|
||||
m_thingTypes[category].resize(count, m_nullThingType);
|
||||
}
|
||||
|
||||
for(int category = 0; category < ThingLastCategory; ++category) {
|
||||
uint16 firstId = 1;
|
||||
if(category == ThingCategoryItem)
|
||||
firstId = 100;
|
||||
for(uint16 id = firstId; id < m_thingTypes[category].size(); ++id) {
|
||||
ThingTypePtr type(new ThingType);
|
||||
type->unserialize(id, (ThingCategory)category, fin);
|
||||
m_thingTypes[category][id] = type;
|
||||
}
|
||||
}
|
||||
|
||||
m_datLoaded = true;
|
||||
return true;
|
||||
} catch(stdext::exception& e) {
|
||||
g_logger.error(stdext::format("Failed to read dat '%s': %s'", file, e.what()));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void ThingTypeManager::loadOtb(const std::string& file)
|
||||
{
|
||||
FileStreamPtr fin = g_resources.openFile(file);
|
||||
|
||||
uint signature = fin->getU32();
|
||||
if(signature != 0)
|
||||
stdext::throw_exception("invalid otb file");
|
||||
|
||||
BinaryTreePtr root = fin->getBinaryTree();
|
||||
|
||||
signature = root->getU32();
|
||||
if(signature != 0)
|
||||
stdext::throw_exception("invalid otb file");
|
||||
|
||||
root->skip(4);
|
||||
|
||||
m_otbMajorVersion = root->getU32();
|
||||
m_otbMinorVersion = root->getU32();
|
||||
root->skip(4);
|
||||
root->skip(128); // description
|
||||
|
||||
m_reverseItemTypes.clear();
|
||||
m_itemTypes.resize(root->getChildren().size() + 1, m_nullItemType);
|
||||
|
||||
for(const BinaryTreePtr& node : root->getChildren()) {
|
||||
ItemTypePtr itemType(new ItemType);
|
||||
itemType->unserialize(node);
|
||||
addItemType(itemType);
|
||||
|
||||
uint16 clientId = itemType->getClientId();
|
||||
if(clientId >= m_reverseItemTypes.size())
|
||||
m_reverseItemTypes.resize(clientId+1);
|
||||
m_reverseItemTypes[clientId] = itemType;
|
||||
}
|
||||
|
||||
m_otbLoaded = true;
|
||||
}
|
||||
|
||||
void ThingTypeManager::loadXml(const std::string& file)
|
||||
{
|
||||
if(!isOtbLoaded())
|
||||
stdext::throw_exception("OTB must be loaded before XML");
|
||||
|
||||
TiXmlDocument doc;
|
||||
doc.Parse(g_resources.loadFile(file).c_str());
|
||||
if(doc.Error())
|
||||
stdext::throw_exception(stdext::format("failed to parse '%s': '%s'", file, doc.ErrorDesc()));
|
||||
|
||||
TiXmlElement* root = doc.FirstChildElement();
|
||||
if(!root || root->ValueTStr() != "items")
|
||||
stdext::throw_exception("invalid root tag name");
|
||||
|
||||
for (TiXmlElement *element = root->FirstChildElement(); element; element = element->NextSiblingElement()) {
|
||||
if(element->ValueTStr() != "item")
|
||||
continue;
|
||||
|
||||
uint16 id = element->readType<uint16>("id");
|
||||
if(id != 0) {
|
||||
std::vector<std::string> s_ids = stdext::split(element->Attribute("id"), ";");
|
||||
for(const std::string& s : s_ids) {
|
||||
std::vector<int32> ids = stdext::split<int32>(s, "-");
|
||||
if(ids.size() > 1) {
|
||||
int32 i = ids[0];
|
||||
while(i <= ids[1])
|
||||
parseItemType(i++, element);
|
||||
} else
|
||||
parseItemType(atoi(s.c_str()), element);
|
||||
}
|
||||
} else {
|
||||
std::vector<int32> begin = stdext::split<int32>(element->Attribute("fromid"), ";");
|
||||
std::vector<int32> end = stdext::split<int32>(element->Attribute("toid"), ";");
|
||||
if(begin[0] && begin.size() == end.size()) {
|
||||
size_t size = begin.size();
|
||||
for(size_t i = 0; i < size; ++i) {
|
||||
while(begin[i] <= end[i])
|
||||
parseItemType(begin[i]++, element);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
doc.Clear();
|
||||
m_xmlLoaded = true;
|
||||
g_logger.debug("items.xml read successfully.");
|
||||
}
|
||||
|
||||
void ThingTypeManager::parseItemType(uint16 id, TiXmlElement* elem)
|
||||
{
|
||||
uint16 serverId = id;
|
||||
ItemTypePtr itemType = nullptr;
|
||||
if(serverId > 20000 && serverId < 20100) {
|
||||
serverId -= 20000;
|
||||
|
||||
itemType = ItemTypePtr(new ItemType);
|
||||
itemType->setServerId(serverId);
|
||||
addItemType(itemType);
|
||||
} else
|
||||
itemType = getItemType(serverId);
|
||||
|
||||
itemType->setName(elem->Attribute("name"));
|
||||
for(TiXmlElement* attrib = elem->FirstChildElement(); attrib; attrib = attrib->NextSiblingElement()) {
|
||||
std::string key = attrib->Attribute("key");
|
||||
if(key.empty())
|
||||
continue;
|
||||
|
||||
stdext::tolower(key);
|
||||
if(key == "description")
|
||||
itemType->setDesc(attrib->Attribute("value"));
|
||||
else if(key == "weapontype")
|
||||
itemType->setCategory(ItemCategoryWeapon);
|
||||
else if(key == "ammotype")
|
||||
itemType->setCategory(ItemCategoryAmmunition);
|
||||
else if(key == "armor")
|
||||
itemType->setCategory(ItemCategoryArmor);
|
||||
else if(key == "charges")
|
||||
itemType->setCategory(ItemCategoryCharges);
|
||||
else if(key == "type") {
|
||||
std::string value = attrib->Attribute("value");
|
||||
stdext::tolower(value);
|
||||
|
||||
if(value == "key")
|
||||
itemType->setCategory(ItemCategoryKey);
|
||||
else if(value == "magicfield")
|
||||
itemType->setCategory(ItemCategoryMagicField);
|
||||
else if(value == "teleport")
|
||||
itemType->setCategory(ItemCategoryTeleport);
|
||||
else if(value == "door")
|
||||
itemType->setCategory(ItemCategoryDoor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ThingTypeManager::addItemType(const ItemTypePtr& itemType)
|
||||
{
|
||||
uint16 id = itemType->getServerId();
|
||||
if(id > m_itemTypes.size())
|
||||
m_itemTypes.resize(id + 1, m_nullItemType);
|
||||
m_itemTypes[id] = itemType;
|
||||
}
|
||||
|
||||
const ItemTypePtr& ThingTypeManager::findItemTypeByClientId(uint16 id)
|
||||
{
|
||||
if(id == 0 || id >= m_reverseItemTypes.size())
|
||||
return m_nullItemType;
|
||||
|
||||
if(m_reverseItemTypes[id])
|
||||
return m_reverseItemTypes[id];
|
||||
else
|
||||
return m_nullItemType;
|
||||
}
|
||||
|
||||
const ThingTypePtr& ThingTypeManager::getThingType(uint16 id, ThingCategory category)
|
||||
{
|
||||
if(category >= ThingLastCategory || id >= m_thingTypes[category].size()) {
|
||||
g_logger.error(stdext::format("invalid thing type client id %d in category %d", id, category));
|
||||
return m_nullThingType;
|
||||
}
|
||||
return m_thingTypes[category][id];
|
||||
}
|
||||
|
||||
const ItemTypePtr& ThingTypeManager::getItemType(uint16 id)
|
||||
{
|
||||
if(id >= m_itemTypes.size() || m_itemTypes[id] == m_nullItemType) {
|
||||
g_logger.error(stdext::format("invalid thing type server id %d", id));
|
||||
return m_nullItemType;
|
||||
}
|
||||
return m_itemTypes[id];
|
||||
}
|
||||
|
||||
ThingTypeList ThingTypeManager::findThingTypeByAttr(ThingAttr attr, ThingCategory category)
|
||||
{
|
||||
ThingTypeList ret;
|
||||
for(const ThingTypePtr& type : m_thingTypes[category])
|
||||
if(type->hasAttr(attr))
|
||||
ret.push_back(type);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ItemTypeList ThingTypeManager::findItemTypeByCategory(ItemCategory category)
|
||||
{
|
||||
ItemTypeList ret;
|
||||
for(const ItemTypePtr& type : m_itemTypes)
|
||||
if(type->getCategory() == category)
|
||||
ret.push_back(type);
|
||||
return ret;
|
||||
}
|
||||
|
||||
const ThingTypeList& ThingTypeManager::getThingTypes(ThingCategory category)
|
||||
{
|
||||
ThingTypeList ret;
|
||||
if(category >= ThingLastCategory)
|
||||
stdext::throw_exception(stdext::format("invalid thing type category %d", category));
|
||||
return m_thingTypes[category];
|
||||
}
|
||||
90
src/client/thingtypemanager.h
Normal file
90
src/client/thingtypemanager.h
Normal file
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Copyright (c) 2010-2013 OTClient <https://github.com/edubart/otclient>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef THINGTYPEMANAGER_H
|
||||
#define THINGTYPEMANAGER_H
|
||||
|
||||
#include <framework/global.h>
|
||||
#include <framework/core/declarations.h>
|
||||
|
||||
#include "thingtype.h"
|
||||
#include "itemtype.h"
|
||||
|
||||
class ThingTypeManager
|
||||
{
|
||||
public:
|
||||
void init();
|
||||
void terminate();
|
||||
|
||||
bool loadDat(const std::string& file);
|
||||
void loadOtb(const std::string& file);
|
||||
void loadXml(const std::string& file);
|
||||
void parseItemType(uint16 id, TiXmlElement *elem);
|
||||
|
||||
void addItemType(const ItemTypePtr& itemType);
|
||||
const ItemTypePtr& findItemTypeByClientId(uint16 id);
|
||||
|
||||
const ThingTypePtr& getNullThingType() { return m_nullThingType; }
|
||||
const ItemTypePtr& getNullItemType() { return m_nullItemType; }
|
||||
|
||||
const ThingTypePtr& getThingType(uint16 id, ThingCategory category);
|
||||
const ItemTypePtr& getItemType(uint16 id);
|
||||
ThingType* rawGetThingType(uint16 id, ThingCategory category) { return m_thingTypes[category][id].get(); }
|
||||
ItemType* rawGetItemType(uint16 id) { return m_itemTypes[id].get(); }
|
||||
|
||||
ThingTypeList findThingTypeByAttr(ThingAttr attr, ThingCategory category);
|
||||
ItemTypeList findItemTypeByCategory(ItemCategory category);
|
||||
|
||||
const ThingTypeList& getThingTypes(ThingCategory category);
|
||||
const ItemTypeList& getItemTypes() { return m_itemTypes; }
|
||||
|
||||
uint32 getDatSignature() { return m_datSignature; }
|
||||
uint32 getOtbMajorVersion() { return m_otbMajorVersion; }
|
||||
uint32 getOtbMinorVersion() { return m_otbMinorVersion; }
|
||||
|
||||
bool isDatLoaded() { return m_datLoaded; }
|
||||
bool isXmlLoaded() { return m_xmlLoaded; }
|
||||
bool isOtbLoaded() { return m_otbLoaded; }
|
||||
|
||||
bool isValidDatId(uint16 id, ThingCategory category) { return id >= 1 && id < m_thingTypes[category].size(); }
|
||||
bool isValidOtbId(uint16 id) { return id >= 1 && id < m_itemTypes.size(); }
|
||||
|
||||
private:
|
||||
ThingTypeList m_thingTypes[ThingLastCategory];
|
||||
ItemTypeList m_reverseItemTypes;
|
||||
ItemTypeList m_itemTypes;
|
||||
|
||||
ThingTypePtr m_nullThingType;
|
||||
ItemTypePtr m_nullItemType;
|
||||
|
||||
bool m_datLoaded;
|
||||
bool m_xmlLoaded;
|
||||
bool m_otbLoaded;
|
||||
|
||||
uint32 m_otbMinorVersion;
|
||||
uint32 m_otbMajorVersion;
|
||||
uint32 m_datSignature;
|
||||
};
|
||||
|
||||
extern ThingTypeManager g_things;
|
||||
|
||||
#endif
|
||||
638
src/client/tile.cpp
Normal file
638
src/client/tile.cpp
Normal file
@@ -0,0 +1,638 @@
|
||||
/*
|
||||
* Copyright (c) 2010-2013 OTClient <https://github.com/edubart/otclient>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "tile.h"
|
||||
#include "item.h"
|
||||
#include "thingtypemanager.h"
|
||||
#include "map.h"
|
||||
#include "game.h"
|
||||
#include "localplayer.h"
|
||||
#include "effect.h"
|
||||
#include "protocolgame.h"
|
||||
#include "lightview.h"
|
||||
#include <framework/graphics/fontmanager.h>
|
||||
|
||||
Tile::Tile(const Position& position) :
|
||||
m_position(position),
|
||||
m_drawElevation(0),
|
||||
m_flags(0)
|
||||
{
|
||||
}
|
||||
|
||||
void Tile::draw(const Point& dest, float scaleFactor, int drawFlags, LightView *lightView)
|
||||
{
|
||||
bool animate = drawFlags & Otc::DrawAnimations;
|
||||
|
||||
// first bottom items
|
||||
if(drawFlags & (Otc::DrawGround | Otc::DrawGroundBorders | Otc::DrawOnBottom)) {
|
||||
m_drawElevation = 0;
|
||||
for(const ThingPtr& thing : m_things) {
|
||||
if(!thing->isGround() && !thing->isGroundBorder() && !thing->isOnBottom())
|
||||
break;
|
||||
|
||||
if((thing->isGround() && drawFlags & Otc::DrawGround) ||
|
||||
(thing->isGroundBorder() && drawFlags & Otc::DrawGroundBorders) ||
|
||||
(thing->isOnBottom() && drawFlags & Otc::DrawOnBottom)) {
|
||||
thing->draw(dest - m_drawElevation*scaleFactor, scaleFactor, animate, lightView);
|
||||
}
|
||||
|
||||
m_drawElevation += thing->getElevation();
|
||||
if(m_drawElevation > Otc::MAX_ELEVATION)
|
||||
m_drawElevation = Otc::MAX_ELEVATION;
|
||||
}
|
||||
}
|
||||
|
||||
int redrawPreviousTopW = 0;
|
||||
int redrawPreviousTopH = 0;
|
||||
|
||||
if(drawFlags & Otc::DrawItems) {
|
||||
// now common items in reverse order
|
||||
for(auto it = m_things.rbegin(); it != m_things.rend(); ++it) {
|
||||
const ThingPtr& thing = *it;
|
||||
if(thing->isOnTop() || thing->isOnBottom() || thing->isGroundBorder() || thing->isGround() || thing->isCreature())
|
||||
break;
|
||||
thing->draw(dest - m_drawElevation*scaleFactor, scaleFactor, animate, lightView);
|
||||
|
||||
if(thing->isLyingCorpse()) {
|
||||
redrawPreviousTopW = std::max(thing->getWidth(), redrawPreviousTopW);
|
||||
redrawPreviousTopH = std::max(thing->getHeight(), redrawPreviousTopH);
|
||||
}
|
||||
|
||||
m_drawElevation += thing->getElevation();
|
||||
if(m_drawElevation > Otc::MAX_ELEVATION)
|
||||
m_drawElevation = Otc::MAX_ELEVATION;
|
||||
}
|
||||
}
|
||||
|
||||
// after we render 2x2 lying corpses, we must redraw previous creatures/ontop above them
|
||||
if(redrawPreviousTopH > 0 || redrawPreviousTopW > 0) {
|
||||
int topRedrawFlags = drawFlags & (Otc::DrawCreatures | Otc::DrawEffects | Otc::DrawOnTop | Otc::DrawAnimations);
|
||||
if(topRedrawFlags) {
|
||||
for(int x=-redrawPreviousTopW;x<=0;++x) {
|
||||
for(int y=-redrawPreviousTopH;y<=0;++y) {
|
||||
if(x == 0 && y == 0)
|
||||
continue;
|
||||
const TilePtr& tile = g_map.getTile(m_position.translated(x,y));
|
||||
if(tile)
|
||||
tile->draw(dest + Point(x*Otc::TILE_PIXELS, y*Otc::TILE_PIXELS)*scaleFactor, scaleFactor, topRedrawFlags);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// creatures
|
||||
if(drawFlags & Otc::DrawCreatures) {
|
||||
if(animate) {
|
||||
for(const CreaturePtr& creature : m_walkingCreatures) {
|
||||
creature->draw(Point(dest.x + ((creature->getPosition().x - m_position.x)*Otc::TILE_PIXELS - m_drawElevation)*scaleFactor,
|
||||
dest.y + ((creature->getPosition().y - m_position.y)*Otc::TILE_PIXELS - m_drawElevation)*scaleFactor), scaleFactor, animate, lightView);
|
||||
}
|
||||
}
|
||||
|
||||
for(auto it = m_things.rbegin(); it != m_things.rend(); ++it) {
|
||||
const ThingPtr& thing = *it;
|
||||
if(!thing->isCreature())
|
||||
continue;
|
||||
CreaturePtr creature = thing->static_self_cast<Creature>();
|
||||
if(creature && (!creature->isWalking() || !animate))
|
||||
creature->draw(dest - m_drawElevation*scaleFactor, scaleFactor, animate, lightView);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// effects
|
||||
if(drawFlags & Otc::DrawEffects) {
|
||||
for(const EffectPtr& effect : m_effects){
|
||||
effect->draw(dest - m_drawElevation*scaleFactor, scaleFactor, animate, lightView);
|
||||
}
|
||||
}
|
||||
|
||||
// top items
|
||||
if(drawFlags & Otc::DrawOnTop) {
|
||||
for(const ThingPtr& thing : m_things) {
|
||||
if(thing->isOnTop()){
|
||||
thing->draw(dest, scaleFactor, animate, lightView);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// draw translucent light (for tiles beneath holes)
|
||||
if(hasTranslucentLight() && lightView) {
|
||||
Light light;
|
||||
light.intensity = 1;
|
||||
lightView->addLightSource(dest + Point(16,16) * scaleFactor, scaleFactor, light);
|
||||
}
|
||||
}
|
||||
|
||||
void Tile::clean()
|
||||
{
|
||||
while(!m_things.empty())
|
||||
removeThing(m_things.front());
|
||||
}
|
||||
|
||||
void Tile::addWalkingCreature(const CreaturePtr& creature)
|
||||
{
|
||||
m_walkingCreatures.push_back(creature);
|
||||
}
|
||||
|
||||
void Tile::removeWalkingCreature(const CreaturePtr& creature)
|
||||
{
|
||||
auto it = std::find(m_walkingCreatures.begin(), m_walkingCreatures.end(), creature);
|
||||
if(it != m_walkingCreatures.end())
|
||||
m_walkingCreatures.erase(it);
|
||||
}
|
||||
|
||||
void Tile::addThing(const ThingPtr& thing, int stackPos)
|
||||
{
|
||||
if(!thing)
|
||||
return;
|
||||
|
||||
if(thing->isEffect()) {
|
||||
m_effects.push_back(thing->static_self_cast<Effect>());
|
||||
} else {
|
||||
// priority 854
|
||||
// 0 - ground, --> -->
|
||||
// 1 - ground borders --> -->
|
||||
// 2 - bottom (walls), --> -->
|
||||
// 3 - on top (doors) --> -->
|
||||
// 4 - creatures, from top to bottom <-- -->
|
||||
// 5 - items, from top to bottom <-- <--
|
||||
if(stackPos < 0 || stackPos == 255) {
|
||||
int priority = thing->getStackPriority();
|
||||
|
||||
// -1 or 255 => auto detect position
|
||||
// -2 => append
|
||||
|
||||
bool append;
|
||||
if(stackPos == -2)
|
||||
append = true;
|
||||
else {
|
||||
append = (priority <= 3);
|
||||
|
||||
// newer protocols does not store creatures in reverse order
|
||||
if(g_game.getProtocolVersion() >= 854 && priority == 4)
|
||||
append = !append;
|
||||
}
|
||||
|
||||
|
||||
for(stackPos = 0; stackPos < (int)m_things.size(); ++stackPos) {
|
||||
int otherPriority = m_things[stackPos]->getStackPriority();
|
||||
if((append && otherPriority > priority) || (!append && otherPriority >= priority))
|
||||
break;
|
||||
}
|
||||
} else if(stackPos > (int)m_things.size())
|
||||
stackPos = m_things.size();
|
||||
|
||||
m_things.insert(m_things.begin() + stackPos, thing);
|
||||
|
||||
if(m_things.size() > MAX_THINGS)
|
||||
removeThing(m_things[MAX_THINGS]);
|
||||
|
||||
/*
|
||||
// check stack priorities
|
||||
// this code exists to find stackpos bugs faster
|
||||
int lastPriority = 0;
|
||||
for(const ThingPtr& thing : m_things) {
|
||||
int priority = thing->getStackPriority();
|
||||
assert(lastPriority <= priority);
|
||||
lastPriority = priority;
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
thing->setPosition(m_position);
|
||||
thing->onAppear();
|
||||
|
||||
if(thing->isTranslucent())
|
||||
checkTranslucentLight();
|
||||
}
|
||||
|
||||
bool Tile::removeThing(ThingPtr thing)
|
||||
{
|
||||
if(!thing)
|
||||
return false;
|
||||
|
||||
bool removed = false;
|
||||
|
||||
if(thing->isEffect()) {
|
||||
EffectPtr effect = thing->static_self_cast<Effect>();
|
||||
auto it = std::find(m_effects.begin(), m_effects.end(), effect);
|
||||
if(it != m_effects.end()) {
|
||||
m_effects.erase(it);
|
||||
removed = true;
|
||||
}
|
||||
} else {
|
||||
auto it = std::find(m_things.begin(), m_things.end(), thing);
|
||||
if(it != m_things.end()) {
|
||||
m_things.erase(it);
|
||||
removed = true;
|
||||
}
|
||||
}
|
||||
|
||||
thing->onDisappear();
|
||||
|
||||
if(thing->isTranslucent())
|
||||
checkTranslucentLight();
|
||||
|
||||
return removed;
|
||||
}
|
||||
|
||||
ThingPtr Tile::getThing(int stackPos)
|
||||
{
|
||||
if(stackPos >= 0 && stackPos < (int)m_things.size())
|
||||
return m_things[stackPos];
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
EffectPtr Tile::getEffect(uint16 id)
|
||||
{
|
||||
for(const EffectPtr& effect : m_effects)
|
||||
if(effect->getId() == id)
|
||||
return effect;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool Tile::hasThing(const ThingPtr& thing)
|
||||
{
|
||||
return std::find(m_things.begin(), m_things.end(), thing) != m_things.end();
|
||||
}
|
||||
|
||||
int Tile::getThingStackpos(const ThingPtr& thing)
|
||||
{
|
||||
for(uint stackpos = 0; stackpos < m_things.size(); ++stackpos) {
|
||||
if(thing == m_things[stackpos])
|
||||
return stackpos;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
ThingPtr Tile:: getTopThing()
|
||||
{
|
||||
if(isEmpty())
|
||||
return nullptr;
|
||||
for(const ThingPtr& thing : m_things) {
|
||||
if(!thing->isGround() && !thing->isGroundBorder() && !thing->isOnBottom() && !thing->isOnTop() && !thing->isCreature())
|
||||
return thing;
|
||||
}
|
||||
return m_things[m_things.size() - 1];
|
||||
}
|
||||
|
||||
std::vector<ItemPtr> Tile::getItems()
|
||||
{
|
||||
std::vector<ItemPtr> items;
|
||||
for(const ThingPtr& thing : m_things) {
|
||||
if(!thing->isItem())
|
||||
continue;
|
||||
ItemPtr item = thing->static_self_cast<Item>();
|
||||
items.push_back(item);
|
||||
}
|
||||
return items;
|
||||
}
|
||||
|
||||
std::vector<CreaturePtr> Tile::getCreatures()
|
||||
{
|
||||
std::vector<CreaturePtr> creatures;
|
||||
for(const ThingPtr& thing : m_things) {
|
||||
if(thing->isCreature())
|
||||
creatures.push_back(thing->static_self_cast<Creature>());
|
||||
}
|
||||
return creatures;
|
||||
}
|
||||
|
||||
ItemPtr Tile::getGround()
|
||||
{
|
||||
ThingPtr firstObject = getThing(0);
|
||||
if(!firstObject)
|
||||
return nullptr;
|
||||
if(firstObject->isGround() && firstObject->isItem())
|
||||
return firstObject->static_self_cast<Item>();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
int Tile::getGroundSpeed()
|
||||
{
|
||||
int groundSpeed = 100;
|
||||
if(ItemPtr ground = getGround())
|
||||
groundSpeed = ground->getGroundSpeed();
|
||||
return groundSpeed;
|
||||
}
|
||||
|
||||
uint8 Tile::getMinimapColorByte()
|
||||
{
|
||||
uint8 color = 0;
|
||||
for(const ThingPtr& thing : m_things) {
|
||||
if(!thing->isGround() && !thing->isGroundBorder() && !thing->isOnBottom() && !thing->isOnTop())
|
||||
break;
|
||||
uint8 c = thing->getMinimapColor();
|
||||
if(c != 0)
|
||||
color = c;
|
||||
}
|
||||
return color;
|
||||
}
|
||||
|
||||
ThingPtr Tile::getTopLookThing()
|
||||
{
|
||||
if(isEmpty())
|
||||
return nullptr;
|
||||
|
||||
for(uint i = 0; i < m_things.size(); ++i) {
|
||||
ThingPtr thing = m_things[i];
|
||||
if(!thing->isIgnoreLook() && (!thing->isGround() && !thing->isGroundBorder() && !thing->isOnBottom() && !thing->isOnTop()))
|
||||
return thing;
|
||||
}
|
||||
|
||||
return m_things[0];
|
||||
}
|
||||
|
||||
ThingPtr Tile::getTopUseThing()
|
||||
{
|
||||
if(isEmpty())
|
||||
return nullptr;
|
||||
|
||||
for(uint i = 0; i < m_things.size(); ++i) {
|
||||
ThingPtr thing = m_things[i];
|
||||
if(thing->isForceUse() || (!thing->isGround() && !thing->isGroundBorder() && !thing->isOnBottom() && !thing->isOnTop() && !thing->isCreature()))
|
||||
return thing;
|
||||
}
|
||||
|
||||
return m_things[0];
|
||||
}
|
||||
|
||||
CreaturePtr Tile::getTopCreature()
|
||||
{
|
||||
CreaturePtr creature;
|
||||
for(uint i = 0; i < m_things.size(); ++i) {
|
||||
ThingPtr thing = m_things[i];
|
||||
if(thing->isLocalPlayer()) // return local player if there is no other creature
|
||||
creature = thing->static_self_cast<Creature>();
|
||||
else if(thing->isCreature() && !thing->isLocalPlayer())
|
||||
return thing->static_self_cast<Creature>();
|
||||
}
|
||||
if(!creature && !m_walkingCreatures.empty())
|
||||
creature = m_walkingCreatures.back();
|
||||
|
||||
// check for walking creatures in tiles around
|
||||
if(!creature) {
|
||||
for(int xi=-1;xi<=1;++xi) {
|
||||
for(int yi=-1;yi<=1;++yi) {
|
||||
Position pos = m_position.translated(xi, yi);
|
||||
if(pos == m_position)
|
||||
continue;
|
||||
|
||||
const TilePtr& tile = g_map.getTile(pos);
|
||||
if(tile) {
|
||||
for(const CreaturePtr& c : tile->getCreatures()) {
|
||||
if(c->isWalking() && c->getLastStepFromPosition() == m_position && c->getStepProgress() < 0.75f) {
|
||||
creature = c;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return creature;
|
||||
}
|
||||
|
||||
ThingPtr Tile::getTopMoveThing()
|
||||
{
|
||||
if(isEmpty())
|
||||
return nullptr;
|
||||
|
||||
for(uint i = 0; i < m_things.size(); ++i) {
|
||||
ThingPtr thing = m_things[i];
|
||||
if(!thing->isGround() && !thing->isGroundBorder() && !thing->isOnBottom() && !thing->isOnTop() && !thing->isCreature()) {
|
||||
if(i > 0 && thing->isNotMoveable())
|
||||
return m_things[i-1];
|
||||
return thing;
|
||||
}
|
||||
}
|
||||
|
||||
for(const ThingPtr& thing : m_things) {
|
||||
if(thing->isCreature())
|
||||
return thing;
|
||||
}
|
||||
|
||||
return m_things[0];
|
||||
}
|
||||
|
||||
ThingPtr Tile::getTopMultiUseThing(bool ignoreCreature)
|
||||
{
|
||||
// this is related to classic controls, getting top item, forceuse for creature
|
||||
if(isEmpty())
|
||||
return nullptr;
|
||||
|
||||
for(uint i = 0; i < m_things.size(); ++i) {
|
||||
ThingPtr thing = m_things[i];
|
||||
if(thing->isForceUse() || (!thing->isGround() && !thing->isGroundBorder() && !thing->isOnBottom() && !thing->isOnTop())) {
|
||||
if(thing->isCreature() && ignoreCreature)
|
||||
continue;
|
||||
if(i > 0 && thing->isSplash())
|
||||
return m_things[i-1];
|
||||
return thing;
|
||||
}
|
||||
}
|
||||
|
||||
for(uint i = 0; i < m_things.size(); ++i) {
|
||||
ThingPtr thing = m_things[i];
|
||||
if(!thing->isGround() && !thing->isGroundBorder() && !thing->isOnTop()) {
|
||||
if(thing->isCreature() && ignoreCreature)
|
||||
continue;
|
||||
return thing;
|
||||
}
|
||||
}
|
||||
|
||||
return m_things[0];
|
||||
}
|
||||
|
||||
bool Tile::isWalkable()
|
||||
{
|
||||
if(!getGround())
|
||||
return false;
|
||||
|
||||
for(const ThingPtr& thing : m_things) {
|
||||
if(thing->isNotWalkable())
|
||||
return false;
|
||||
|
||||
if(thing->isCreature()) {
|
||||
CreaturePtr creature = thing->static_self_cast<Creature>();
|
||||
if(!creature->isPassable() && creature->canBeSeen())
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Tile::changesFloor()
|
||||
{
|
||||
for(const ThingPtr& thing : m_things) {
|
||||
if(thing->isTranslucent() || (thing->isOnBottom() && thing->hasElevation()))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Tile::isPathable()
|
||||
{
|
||||
for(const ThingPtr& thing : m_things) {
|
||||
if(thing->isNotPathable())
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Tile::isFullGround()
|
||||
{
|
||||
ItemPtr ground = getGround();
|
||||
if(ground && ground->isFullGround())
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Tile::isFullyOpaque()
|
||||
{
|
||||
ThingPtr firstObject = getThing(0);
|
||||
return firstObject && firstObject->isFullGround();
|
||||
}
|
||||
|
||||
bool Tile::isSingleDimension()
|
||||
{
|
||||
if(!m_walkingCreatures.empty())
|
||||
return false;
|
||||
for(const ThingPtr& thing : m_things) {
|
||||
if(thing->getHeight() != 1 || thing->getWidth() != 1)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Tile::isLookPossible()
|
||||
{
|
||||
for(const ThingPtr& thing : m_things) {
|
||||
if(thing->blockProjectile())
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Tile::isClickable()
|
||||
{
|
||||
bool hasGround = false;
|
||||
bool hasOnBottom = false;
|
||||
bool hasIgnoreLook = false;
|
||||
for(const ThingPtr& thing : m_things) {
|
||||
if(thing->isGround())
|
||||
hasGround = true;
|
||||
if(thing->isOnBottom())
|
||||
hasOnBottom = true;
|
||||
if(thing->isIgnoreLook())
|
||||
hasIgnoreLook = true;
|
||||
|
||||
if((hasGround || hasOnBottom) && !hasIgnoreLook)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Tile::isEmpty()
|
||||
{
|
||||
return m_things.size() == 0;
|
||||
}
|
||||
|
||||
bool Tile::isDrawable()
|
||||
{
|
||||
return !m_things.empty() || !m_walkingCreatures.empty() || !m_effects.empty();
|
||||
}
|
||||
|
||||
bool Tile::mustHookEast()
|
||||
{
|
||||
for(const ThingPtr& thing : m_things)
|
||||
if(thing->isHookEast())
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Tile::mustHookSouth()
|
||||
{
|
||||
for(const ThingPtr& thing : m_things)
|
||||
if(thing->isHookSouth())
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Tile::hasCreature()
|
||||
{
|
||||
for(const ThingPtr& thing : m_things)
|
||||
if(thing->isCreature())
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Tile::limitsFloorsView()
|
||||
{
|
||||
// ground and walls limits the view
|
||||
ThingPtr firstThing = getThing(0);
|
||||
if(firstThing && !firstThing->isDontHide() && (firstThing->isGround() || firstThing->isOnBottom()))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Tile::canErase()
|
||||
{
|
||||
return m_walkingCreatures.empty() && m_effects.empty() && m_things.empty() && m_flags == 0;
|
||||
}
|
||||
|
||||
bool Tile::hasElevation(int elevation)
|
||||
{
|
||||
int count = 0;
|
||||
for(const ThingPtr& thing : m_things)
|
||||
if(thing->getElevation() > 0)
|
||||
count++;
|
||||
return count >= elevation;
|
||||
}
|
||||
|
||||
void Tile::checkTranslucentLight()
|
||||
{
|
||||
if(m_position.z != Otc::SEA_FLOOR)
|
||||
return;
|
||||
|
||||
Position downPos = m_position;
|
||||
if(!downPos.down())
|
||||
return;
|
||||
|
||||
TilePtr tile = g_map.getOrCreateTile(downPos);
|
||||
if(!tile)
|
||||
return;
|
||||
|
||||
bool translucent = false;
|
||||
for(const ThingPtr& thing : m_things) {
|
||||
if(thing->isTranslucent() || thing->hasLensHelp()) {
|
||||
translucent = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(translucent)
|
||||
tile->m_flags = tile->m_flags | TILESTATE_TRANSLUECENT_LIGHT;
|
||||
else
|
||||
tile->m_flags = tile->m_flags & ~TILESTATE_TRANSLUECENT_LIGHT;
|
||||
}
|
||||
135
src/client/tile.h
Normal file
135
src/client/tile.h
Normal file
@@ -0,0 +1,135 @@
|
||||
/*
|
||||
* Copyright (c) 2010-2013 OTClient <https://github.com/edubart/otclient>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef TILE_H
|
||||
#define TILE_H
|
||||
|
||||
#include "declarations.h"
|
||||
#include "mapview.h"
|
||||
#include "effect.h"
|
||||
#include "creature.h"
|
||||
#include "item.h"
|
||||
#include <framework/luaengine/luaobject.h>
|
||||
|
||||
enum tileflags_t
|
||||
{
|
||||
TILESTATE_NONE = 0,
|
||||
TILESTATE_PROTECTIONZONE = 1 << 0,
|
||||
TILESTATE_TRASHED = 1 << 1,
|
||||
TILESTATE_OPTIONALZONE = 1 << 2,
|
||||
TILESTATE_NOLOGOUT = 1 << 3,
|
||||
TILESTATE_HARDCOREZONE = 1 << 4,
|
||||
TILESTATE_REFRESH = 1 << 5,
|
||||
|
||||
// internal usage
|
||||
TILESTATE_HOUSE = 1 << 6,
|
||||
TILESTATE_TELEPORT = 1 << 17,
|
||||
TILESTATE_MAGICFIELD = 1 << 18,
|
||||
TILESTATE_MAILBOX = 1 << 19,
|
||||
TILESTATE_TRASHHOLDER = 1 << 20,
|
||||
TILESTATE_BED = 1 << 21,
|
||||
TILESTATE_DEPOT = 1 << 22,
|
||||
TILESTATE_TRANSLUECENT_LIGHT = 1 << 23
|
||||
};
|
||||
|
||||
#pragma pack(push,1) // disable memory alignment
|
||||
class Tile : public LuaObject
|
||||
{
|
||||
public:
|
||||
enum {
|
||||
MAX_THINGS = 10
|
||||
};
|
||||
|
||||
Tile(const Position& position);
|
||||
|
||||
void draw(const Point& dest, float scaleFactor, int drawFlags, LightView *lightView = nullptr);
|
||||
|
||||
public:
|
||||
void clean();
|
||||
|
||||
void addWalkingCreature(const CreaturePtr& creature);
|
||||
void removeWalkingCreature(const CreaturePtr& creature);
|
||||
|
||||
void addThing(const ThingPtr& thing, int stackPos);
|
||||
bool removeThing(ThingPtr thing);
|
||||
ThingPtr getThing(int stackPos);
|
||||
EffectPtr getEffect(uint16 id);
|
||||
bool hasThing(const ThingPtr& thing);
|
||||
int getThingStackpos(const ThingPtr& thing);
|
||||
ThingPtr getTopThing();
|
||||
|
||||
ThingPtr getTopLookThing();
|
||||
ThingPtr getTopUseThing();
|
||||
CreaturePtr getTopCreature();
|
||||
ThingPtr getTopMoveThing();
|
||||
ThingPtr getTopMultiUseThing(bool ignoreCreature = true);
|
||||
|
||||
const Position& getPosition() { return m_position; }
|
||||
int getDrawElevation() { return m_drawElevation; }
|
||||
std::vector<ItemPtr> getItems();
|
||||
std::vector<CreaturePtr> getCreatures();
|
||||
std::vector<CreaturePtr> getWalkingCreatures() { return m_walkingCreatures; }
|
||||
std::vector<ThingPtr> getThings() { return m_things; }
|
||||
ItemPtr getGround();
|
||||
int getGroundSpeed();
|
||||
uint8 getMinimapColorByte();
|
||||
int getThingCount() { return m_things.size() + m_effects.size(); }
|
||||
bool isPathable();
|
||||
bool isWalkable();
|
||||
bool changesFloor();
|
||||
bool isFullGround();
|
||||
bool isFullyOpaque();
|
||||
bool isSingleDimension();
|
||||
bool isLookPossible();
|
||||
bool isClickable();
|
||||
bool isEmpty();
|
||||
bool isDrawable();
|
||||
bool hasTranslucentLight() { return m_flags & TILESTATE_TRANSLUECENT_LIGHT; }
|
||||
bool mustHookSouth();
|
||||
bool mustHookEast();
|
||||
bool hasCreature();
|
||||
bool limitsFloorsView();
|
||||
bool canErase();
|
||||
bool hasElevation(int elevation = 1);
|
||||
|
||||
void setFlags(tileflags_t flags) { m_flags |= (uint32)flags; }
|
||||
uint32 getFlags() { return m_flags; }
|
||||
|
||||
void setHouseId(uint32 hid) { m_houseId = hid; }
|
||||
uint32 getHouseId() { return m_houseId; }
|
||||
bool isHouseTile() const { return (m_flags & TILESTATE_HOUSE) == TILESTATE_HOUSE; }
|
||||
|
||||
TilePtr asTile() { return static_self_cast<Tile>(); }
|
||||
|
||||
private:
|
||||
void checkTranslucentLight();
|
||||
|
||||
stdext::packed_vector<CreaturePtr> m_walkingCreatures;
|
||||
stdext::packed_vector<EffectPtr> m_effects; // leave this outside m_things because it has no stackpos.
|
||||
stdext::packed_vector<ThingPtr> m_things;
|
||||
Position m_position;
|
||||
uint8 m_drawElevation;
|
||||
uint32 m_flags, m_houseId;
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
#endif
|
||||
65
src/client/towns.cpp
Normal file
65
src/client/towns.cpp
Normal file
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright (c) 2010-2013 OTClient <https://github.com/edubart/otclient>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "towns.h"
|
||||
|
||||
TownManager g_towns;
|
||||
|
||||
Town::Town(uint32 tid, const std::string& name, const Position& pos)
|
||||
: m_id(tid), m_name(name)
|
||||
{
|
||||
if(pos.isValid())
|
||||
m_pos = pos;
|
||||
}
|
||||
|
||||
TownManager::TownManager()
|
||||
{
|
||||
m_nullTown = TownPtr(new Town);
|
||||
}
|
||||
|
||||
void TownManager::addTown(const TownPtr &town)
|
||||
{
|
||||
if(findTown(town->getId()) == m_towns.end())
|
||||
m_towns.push_back(town);
|
||||
}
|
||||
|
||||
void TownManager::removeTown(uint32 townId)
|
||||
{
|
||||
auto it = findTown(townId);
|
||||
if(it != m_towns.end())
|
||||
m_towns.erase(it);
|
||||
}
|
||||
|
||||
const TownPtr& TownManager::getTown(uint32 townId)
|
||||
{
|
||||
auto it = std::find_if(m_towns.begin(), m_towns.end(),
|
||||
[=] (const TownPtr& town) -> bool { return town->getId() == townId; });
|
||||
if(it != m_towns.end())
|
||||
return *it;
|
||||
return m_nullTown;
|
||||
}
|
||||
|
||||
TownList::iterator TownManager::findTown(uint32 townId)
|
||||
{
|
||||
return std::find_if(m_towns.begin(), m_towns.end(),
|
||||
[=] (const TownPtr& town) -> bool { return town->getId() == townId; });
|
||||
}
|
||||
71
src/client/towns.h
Normal file
71
src/client/towns.h
Normal file
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Copyright (c) 2010-2013 OTClient <https://github.com/edubart/otclient>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef TOWNS_H
|
||||
#define TOWNS_H
|
||||
|
||||
#include "declarations.h"
|
||||
#include <framework/luaengine/luaobject.h>
|
||||
|
||||
class Town : public LuaObject
|
||||
{
|
||||
public:
|
||||
Town() { }
|
||||
Town(uint32 tid, const std::string& name, const Position& pos=Position());
|
||||
|
||||
void setId(uint32 tid) { m_id = tid; }
|
||||
void setName(const std::string& name) { m_name = name; }
|
||||
void setPos(const Position& pos) { m_pos = pos; }
|
||||
|
||||
uint32 getId() { return m_id; }
|
||||
std::string getName() { return m_name; }
|
||||
Position getPos() { return m_pos; }
|
||||
|
||||
private:
|
||||
uint32 m_id;
|
||||
std::string m_name;
|
||||
Position m_pos; // temple pos
|
||||
};
|
||||
|
||||
class TownManager
|
||||
{
|
||||
public:
|
||||
TownManager();
|
||||
|
||||
void addTown(const TownPtr& town);
|
||||
void removeTown(uint32 townId);
|
||||
const TownPtr& getTown(uint32 townId);
|
||||
|
||||
TownList getTowns() { return m_towns; }
|
||||
void clear() { m_towns.clear(); m_nullTown = nullptr; }
|
||||
|
||||
private:
|
||||
TownList m_towns;
|
||||
TownPtr m_nullTown;
|
||||
|
||||
protected:
|
||||
TownList::iterator findTown(uint32 townId);
|
||||
};
|
||||
|
||||
extern TownManager g_towns;
|
||||
|
||||
#endif
|
||||
57
src/client/uicreature.cpp
Normal file
57
src/client/uicreature.cpp
Normal file
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright (c) 2010-2013 OTClient <https://github.com/edubart/otclient>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "uicreature.h"
|
||||
#include <framework/otml/otml.h>
|
||||
#include <framework/graphics/graphics.h>
|
||||
|
||||
void UICreature::drawSelf(Fw::DrawPane drawPane)
|
||||
{
|
||||
if((drawPane & Fw::ForegroundPane) == 0)
|
||||
return;
|
||||
|
||||
UIWidget::drawSelf(drawPane);
|
||||
|
||||
if(m_creature) {
|
||||
Rect drawRect = getPaddingRect();
|
||||
g_painter->setColor(Color::white);
|
||||
m_creature->drawOutfit(drawRect, !m_fixedCreatureSize);
|
||||
}
|
||||
}
|
||||
|
||||
void UICreature::setOutfit(const Outfit& outfit)
|
||||
{
|
||||
if(!m_creature)
|
||||
m_creature = CreaturePtr(new Creature);
|
||||
m_creature->setDirection(Otc::South);
|
||||
m_creature->setOutfit(outfit);
|
||||
}
|
||||
|
||||
void UICreature::onStyleApply(const std::string& styleName, const OTMLNodePtr& styleNode)
|
||||
{
|
||||
UIWidget::onStyleApply(styleName, styleNode);
|
||||
|
||||
for(const OTMLNodePtr& node : styleNode->children()) {
|
||||
if(node->tag() == "fixed-creature-size")
|
||||
setFixedCreatureSize(node->value<bool>());
|
||||
}
|
||||
}
|
||||
49
src/client/uicreature.h
Normal file
49
src/client/uicreature.h
Normal file
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright (c) 2010-2013 OTClient <https://github.com/edubart/otclient>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef UICREATURE_H
|
||||
#define UICREATURE_H
|
||||
|
||||
#include "declarations.h"
|
||||
#include <framework/ui/uiwidget.h>
|
||||
#include "creature.h"
|
||||
|
||||
class UICreature : public UIWidget
|
||||
{
|
||||
public:
|
||||
void drawSelf(Fw::DrawPane drawPane);
|
||||
|
||||
void setCreature(const CreaturePtr& creature) { m_creature = creature; }
|
||||
void setFixedCreatureSize(bool fixed) { m_fixedCreatureSize = fixed; }
|
||||
void setOutfit(const Outfit& outfit);
|
||||
|
||||
CreaturePtr getCreature() { return m_creature; }
|
||||
bool isFixedCreatureSize() { return m_fixedCreatureSize; }
|
||||
|
||||
protected:
|
||||
void onStyleApply(const std::string& styleName, const OTMLNodePtr& styleNode);
|
||||
|
||||
CreaturePtr m_creature;
|
||||
stdext::boolean<false> m_fixedCreatureSize;
|
||||
};
|
||||
|
||||
#endif
|
||||
103
src/client/uiitem.cpp
Normal file
103
src/client/uiitem.cpp
Normal file
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
* Copyright (c) 2010-2013 OTClient <https://github.com/edubart/otclient>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "uiitem.h"
|
||||
#include <framework/otml/otml.h>
|
||||
#include <framework/graphics/graphics.h>
|
||||
#include <framework/graphics/fontmanager.h>
|
||||
|
||||
UIItem::UIItem()
|
||||
{
|
||||
m_draggable = true;
|
||||
}
|
||||
|
||||
void UIItem::drawSelf(Fw::DrawPane drawPane)
|
||||
{
|
||||
if((drawPane & Fw::ForegroundPane) == 0)
|
||||
return;
|
||||
|
||||
// draw style components in order
|
||||
if(m_backgroundColor.aF() > Fw::MIN_ALPHA) {
|
||||
Rect backgroundDestRect = m_rect;
|
||||
backgroundDestRect.expand(-m_borderWidth.top, -m_borderWidth.right, -m_borderWidth.bottom, -m_borderWidth.left);
|
||||
drawBackground(m_rect);
|
||||
}
|
||||
|
||||
drawImage(m_rect);
|
||||
|
||||
if(m_item) {
|
||||
Rect drawRect = getPaddingRect();
|
||||
Point dest = drawRect.bottomRight() + Point(1,1);
|
||||
|
||||
int exactSize = std::max(32, m_item->getExactSize());
|
||||
if(exactSize == 0)
|
||||
return;
|
||||
|
||||
float scaleFactor = std::min(drawRect.width() / (float)exactSize, drawRect.height() / (float)exactSize);
|
||||
dest += (m_item->getDisplacement() - Point(32,32)) * scaleFactor;
|
||||
|
||||
if(isEnabled())
|
||||
g_painter->setColor(Color::white);
|
||||
else
|
||||
g_painter->setColor(Color(100, 100, 100));
|
||||
m_item->draw(dest, scaleFactor, true);
|
||||
|
||||
if(m_font && (m_item->isStackable() || m_item->isChargeable()) && m_item->getCountOrSubType() > 1) {
|
||||
std::string count = stdext::to_string(m_item->getCount());
|
||||
g_painter->setColor(Color(231, 231, 231));
|
||||
m_font->drawText(count, Rect(m_rect.topLeft(), m_rect.bottomRight() - Point(3, 0)), Fw::AlignBottomRight);
|
||||
}
|
||||
// debug, show item id
|
||||
//m_font->drawText(stdext::to_string(m_item->getId()), m_rect, Fw::AlignBottomRight);
|
||||
}
|
||||
|
||||
drawBorder(m_rect);
|
||||
drawIcon(m_rect);
|
||||
drawText(m_rect);
|
||||
}
|
||||
|
||||
void UIItem::setItemId(int id)
|
||||
{
|
||||
if(!m_item && id != 0)
|
||||
m_item = Item::create(id);
|
||||
else {
|
||||
// remove item
|
||||
if(id == 0)
|
||||
m_item = nullptr;
|
||||
else
|
||||
m_item->setId(id);
|
||||
}
|
||||
}
|
||||
|
||||
void UIItem::onStyleApply(const std::string& styleName, const OTMLNodePtr& styleNode)
|
||||
{
|
||||
UIWidget::onStyleApply(styleName, styleNode);
|
||||
|
||||
for(const OTMLNodePtr& node : styleNode->children()) {
|
||||
if(node->tag() == "item-id")
|
||||
setItemId(node->value<int>());
|
||||
else if(node->tag() == "item-count")
|
||||
setItemCount(node->value<int>());
|
||||
else if(node->tag() == "virtual")
|
||||
setVirtual(node->value<bool>());
|
||||
}
|
||||
}
|
||||
56
src/client/uiitem.h
Normal file
56
src/client/uiitem.h
Normal file
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright (c) 2010-2013 OTClient <https://github.com/edubart/otclient>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef UIITEM_H
|
||||
#define UIITEM_H
|
||||
|
||||
#include "declarations.h"
|
||||
#include <framework/ui/uiwidget.h>
|
||||
#include "item.h"
|
||||
|
||||
class UIItem : public UIWidget
|
||||
{
|
||||
public:
|
||||
UIItem();
|
||||
void drawSelf(Fw::DrawPane drawPane);
|
||||
|
||||
void setItemId(int id);
|
||||
void setItemCount(int count) { if(m_item) m_item->setCount(count); }
|
||||
void setItemSubType(int subType) { if(m_item) m_item->setSubType(subType); }
|
||||
void setItem(const ItemPtr& item) { m_item = item; }
|
||||
void setVirtual(bool virt) { m_virtual = virt; }
|
||||
void clearItem() { setItemId(0); }
|
||||
|
||||
int getItemId() { return m_item ? m_item->getId() : 0; }
|
||||
int getItemCount() { return m_item ? m_item->getCount() : 0; }
|
||||
int getItemSubType() { return m_item ? m_item->getSubType() : 0; }
|
||||
ItemPtr getItem() { return m_item; }
|
||||
bool isVirtual() { return m_virtual; }
|
||||
|
||||
protected:
|
||||
void onStyleApply(const std::string& styleName, const OTMLNodePtr& styleNode);
|
||||
|
||||
ItemPtr m_item;
|
||||
stdext::boolean<false> m_virtual;
|
||||
};
|
||||
|
||||
#endif
|
||||
235
src/client/uimap.cpp
Normal file
235
src/client/uimap.cpp
Normal file
@@ -0,0 +1,235 @@
|
||||
/*
|
||||
* Copyright (c) 2010-2013 OTClient <https://github.com/edubart/otclient>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "uimap.h"
|
||||
#include "game.h"
|
||||
#include "map.h"
|
||||
#include "mapview.h"
|
||||
#include <framework/otml/otml.h>
|
||||
#include <framework/graphics/graphics.h>
|
||||
#include "localplayer.h"
|
||||
|
||||
UIMap::UIMap()
|
||||
{
|
||||
m_draggable = true;
|
||||
m_mapView = MapViewPtr(new MapView);
|
||||
m_zoom = m_mapView->getVisibleDimension().height();
|
||||
m_aspectRatio = 0.0f;
|
||||
m_maxZoomIn = 3;
|
||||
m_maxZoomOut = 512;
|
||||
m_mapRect.resize(1,1);
|
||||
g_map.addMapView(m_mapView);
|
||||
}
|
||||
|
||||
UIMap::~UIMap()
|
||||
{
|
||||
g_map.removeMapView(m_mapView);
|
||||
}
|
||||
|
||||
void UIMap::drawSelf(Fw::DrawPane drawPane)
|
||||
{
|
||||
UIWidget::drawSelf(drawPane);
|
||||
|
||||
if(drawPane & Fw::ForegroundPane) {
|
||||
// draw map border
|
||||
g_painter->setColor(Color::black);
|
||||
g_painter->drawBoundingRect(m_mapRect.expanded(1));
|
||||
|
||||
if(drawPane != Fw::BothPanes) {
|
||||
glDisable(GL_BLEND);
|
||||
g_painter->setColor(Color::alpha);
|
||||
g_painter->drawFilledRect(m_mapRect);
|
||||
glEnable(GL_BLEND);
|
||||
}
|
||||
}
|
||||
|
||||
if(drawPane & Fw::BackgroundPane) {
|
||||
g_painter->setColor(Color::white);
|
||||
m_mapView->draw(m_mapRect);
|
||||
}
|
||||
}
|
||||
|
||||
bool UIMap::setZoom(int zoom)
|
||||
{
|
||||
m_zoom = std::min(std::max(zoom, m_maxZoomIn), m_maxZoomOut);
|
||||
updateVisibleDimension();
|
||||
return false;
|
||||
}
|
||||
|
||||
bool UIMap::zoomIn()
|
||||
{
|
||||
int delta = 2;
|
||||
if(m_zoom - delta <= m_maxZoomIn)
|
||||
return false;
|
||||
|
||||
m_zoom -= delta;
|
||||
updateVisibleDimension();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool UIMap::zoomOut()
|
||||
{
|
||||
int delta = 2;
|
||||
if(m_zoom + delta >= m_maxZoomOut)
|
||||
return false;
|
||||
|
||||
m_zoom += 2;
|
||||
updateVisibleDimension();
|
||||
return true;
|
||||
}
|
||||
|
||||
void UIMap::setVisibleDimension(const Size& visibleDimension)
|
||||
{
|
||||
m_mapView->setVisibleDimension(visibleDimension);
|
||||
|
||||
if(m_aspectRatio != 0.0f) {
|
||||
m_aspectRatio = visibleDimension.ratio();
|
||||
updateMapSize();
|
||||
}
|
||||
}
|
||||
|
||||
void UIMap::setKeepAspectRatio(bool enable)
|
||||
{
|
||||
if(enable)
|
||||
m_aspectRatio = getVisibleDimension().ratio();
|
||||
else
|
||||
m_aspectRatio = 0.0f;
|
||||
updateMapSize();
|
||||
}
|
||||
|
||||
Position UIMap::getPosition(const Point& mousePos)
|
||||
{
|
||||
if(!m_mapRect.contains(mousePos))
|
||||
return Position();
|
||||
|
||||
Point relativeMousePos = mousePos - m_mapRect.topLeft();
|
||||
Size visibleSize = getVisibleDimension() * m_mapView->getTileSize();
|
||||
Position cameraPosition = getCameraPosition();
|
||||
|
||||
// if we have no camera, its impossible to get the tile
|
||||
if(!cameraPosition.isValid())
|
||||
return Position();
|
||||
|
||||
float scaleFactor = m_mapView->getTileSize() / (float)Otc::TILE_PIXELS;
|
||||
float horizontalStretchFactor = visibleSize.width() / (float)m_mapRect.width();
|
||||
float verticalStretchFactor = visibleSize.height() / (float)m_mapRect.height();
|
||||
|
||||
Point tilePos2D = Point(relativeMousePos.x * horizontalStretchFactor, relativeMousePos.y * verticalStretchFactor);
|
||||
|
||||
if(m_mapView->isFollowingCreature())
|
||||
tilePos2D += getFollowingCreature()->getWalkOffset() * scaleFactor;
|
||||
tilePos2D /= m_mapView->getTileSize();
|
||||
|
||||
Point visibleCenterOffset = m_mapView->getVisibleCenterOffset();
|
||||
Position position = Position(1 + (int)tilePos2D.x - visibleCenterOffset.x, 1 + (int)tilePos2D.y - visibleCenterOffset.y, 0) + cameraPosition;
|
||||
if(!position.isValid())
|
||||
return Position();
|
||||
|
||||
return position;
|
||||
}
|
||||
|
||||
TilePtr UIMap::getTile(const Point& mousePos)
|
||||
{
|
||||
Position tilePos = getPosition(mousePos);
|
||||
if(!tilePos.isValid())
|
||||
return nullptr;
|
||||
|
||||
// we must check every floor, from top to bottom to check for a clickable tile
|
||||
TilePtr tile;
|
||||
tilePos.coveredUp(tilePos.z - m_mapView->getCachedFirstVisibleFloor());
|
||||
for(int i = m_mapView->getCachedFirstVisibleFloor(); i <= m_mapView->getCachedLastVisibleFloor(); i++) {
|
||||
tile = g_map.getTile(tilePos);
|
||||
if(tile && tile->isClickable())
|
||||
break;
|
||||
tilePos.coveredDown();
|
||||
}
|
||||
|
||||
if(!tile || !tile->isClickable())
|
||||
return nullptr;
|
||||
|
||||
return tile;
|
||||
}
|
||||
|
||||
void UIMap::onStyleApply(const std::string& styleName, const OTMLNodePtr& styleNode)
|
||||
{
|
||||
UIWidget::onStyleApply(styleName, styleNode);
|
||||
for(const OTMLNodePtr& node : styleNode->children()) {
|
||||
if(node->tag() == "multifloor")
|
||||
setMultifloor(node->value<bool>());
|
||||
else if(node->tag() == "auto-view-mode")
|
||||
setAutoViewMode(node->value<bool>());
|
||||
else if(node->tag() == "draw-texts")
|
||||
setDrawTexts(node->value<bool>());
|
||||
else if(node->tag() == "draw-minimap-colors")
|
||||
setDrawMinimapColors(node->value<bool>());
|
||||
else if(node->tag() == "draw-lights")
|
||||
setDrawLights(node->value<bool>());
|
||||
else if(node->tag() == "animated")
|
||||
setAnimated(node->value<bool>());
|
||||
}
|
||||
}
|
||||
|
||||
void UIMap::onGeometryChange(const Rect& oldRect, const Rect& newRect)
|
||||
{
|
||||
UIWidget::onGeometryChange(oldRect, newRect);
|
||||
updateMapSize();
|
||||
}
|
||||
|
||||
void UIMap::updateVisibleDimension()
|
||||
{
|
||||
int dimensionHeight = m_zoom;
|
||||
|
||||
float ratio = 1;
|
||||
if(!m_mapRect.isEmpty())
|
||||
ratio = m_mapRect.size().ratio();
|
||||
|
||||
if(dimensionHeight % 2 == 0)
|
||||
dimensionHeight += 1;
|
||||
int dimensionWidth = m_zoom * ratio;
|
||||
if(dimensionWidth % 2 == 0)
|
||||
dimensionWidth += 1;
|
||||
|
||||
m_mapView->setVisibleDimension(Size(dimensionWidth, dimensionHeight));
|
||||
|
||||
if(m_aspectRatio != 0.0f)
|
||||
updateMapSize();
|
||||
}
|
||||
|
||||
void UIMap::updateMapSize()
|
||||
{
|
||||
Rect clippingRect = getPaddingRect();
|
||||
Size mapSize;
|
||||
if(m_aspectRatio != 0.0f) {
|
||||
Rect mapRect = clippingRect.expanded(-1);
|
||||
mapSize = Size(m_aspectRatio*m_zoom, m_zoom);
|
||||
mapSize.scale(mapRect.size(), Fw::KeepAspectRatio);
|
||||
} else {
|
||||
mapSize = clippingRect.expanded(-1).size();
|
||||
}
|
||||
|
||||
m_mapRect.resize(mapSize);
|
||||
m_mapRect.moveCenter(clippingRect.center());
|
||||
m_mapView->optimizeForSize(mapSize);
|
||||
|
||||
if(m_aspectRatio == 0.0f)
|
||||
updateVisibleDimension();
|
||||
}
|
||||
98
src/client/uimap.h
Normal file
98
src/client/uimap.h
Normal file
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
* Copyright (c) 2010-2013 OTClient <https://github.com/edubart/otclient>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef UIMAP_H
|
||||
#define UIMAP_H
|
||||
|
||||
#include "declarations.h"
|
||||
#include <framework/ui/uiwidget.h>
|
||||
#include "tile.h"
|
||||
|
||||
#include "mapview.h"
|
||||
|
||||
class UIMap : public UIWidget
|
||||
{
|
||||
public:
|
||||
UIMap();
|
||||
~UIMap();
|
||||
|
||||
void drawSelf(Fw::DrawPane drawPane);
|
||||
|
||||
bool setZoom(int zoom);
|
||||
bool zoomIn();
|
||||
bool zoomOut();
|
||||
void followCreature(const CreaturePtr& creature) { m_mapView->followCreature(creature); }
|
||||
|
||||
void setCameraPosition(const Position& pos) { m_mapView->setCameraPosition(pos); }
|
||||
void setMaxZoomIn(int maxZoomIn) { m_maxZoomIn = maxZoomIn; }
|
||||
void setMaxZoomOut(int maxZoomOut) { m_maxZoomOut = maxZoomOut; }
|
||||
void setMultifloor(bool enable) { m_mapView->setMultifloor(enable); }
|
||||
void setVisibleDimension(const Size& visibleDimension);
|
||||
void setViewMode(MapView::ViewMode viewMode) { m_mapView->setViewMode(viewMode); }
|
||||
void setAutoViewMode(bool enable) { m_mapView->setAutoViewMode(enable); }
|
||||
void setDrawFlags(Otc::DrawFlags drawFlags) { m_mapView->setDrawFlags(drawFlags); }
|
||||
void setDrawTexts(bool enable) { m_mapView->setDrawTexts(enable); }
|
||||
void setDrawMinimapColors(bool enable) { m_mapView->setDrawMinimapColors(enable); }
|
||||
void setDrawLights(bool enable) { m_mapView->setDrawLights(enable); }
|
||||
void setAnimated(bool enable) { m_mapView->setAnimated(enable); }
|
||||
void setKeepAspectRatio(bool enable);
|
||||
void setMapShader(const PainterShaderProgramPtr& shader) { m_mapView->setShader(shader); }
|
||||
void setMinimumAmbientLight(float intensity) { m_mapView->setMinimumAmbientLight(intensity); }
|
||||
|
||||
bool isMultifloor() { return m_mapView->isMultifloor(); }
|
||||
bool isAutoViewModeEnabled() { return m_mapView->isAutoViewModeEnabled(); }
|
||||
bool isDrawingTexts() { return m_mapView->isDrawingTexts(); }
|
||||
bool isDrawingMinimapColors() { return m_mapView->isDrawingMinimapColors(); }
|
||||
bool isDrawingLights() { return m_mapView->isDrawingLights(); }
|
||||
bool isAnimating() { return m_mapView->isAnimating(); }
|
||||
bool isKeepAspectRatioEnabled() { return m_aspectRatio != 0.0f; }
|
||||
|
||||
Size getVisibleDimension() { return m_mapView->getVisibleDimension(); }
|
||||
MapView::ViewMode getViewMode() { return m_mapView->getViewMode(); }
|
||||
CreaturePtr getFollowingCreature() { return m_mapView->getFollowingCreature(); }
|
||||
Otc::DrawFlags getDrawFlags() { return m_mapView->getDrawFlags(); }
|
||||
Position getCameraPosition() { return m_mapView->getCameraPosition(); }
|
||||
Position getPosition(const Point& mousePos);
|
||||
TilePtr getTile(const Point& mousePos);
|
||||
int getMaxZoomIn() { return m_maxZoomIn; }
|
||||
int getMaxZoomOut() { return m_maxZoomOut; }
|
||||
int getZoom() { return m_zoom; }
|
||||
PainterShaderProgramPtr getMapShader() { return m_mapView->getShader(); }
|
||||
float getMinimumAmbientLight() { return m_mapView->getMinimumAmbientLight(); }
|
||||
|
||||
protected:
|
||||
virtual void onStyleApply(const std::string& styleName, const OTMLNodePtr& styleNode);
|
||||
virtual void onGeometryChange(const Rect& oldRect, const Rect& newRect);
|
||||
|
||||
private:
|
||||
void updateVisibleDimension();
|
||||
void updateMapSize();
|
||||
|
||||
int m_zoom;
|
||||
MapViewPtr m_mapView;
|
||||
Rect m_mapRect;
|
||||
float m_aspectRatio;
|
||||
int m_maxZoomIn;
|
||||
int m_maxZoomOut;
|
||||
};
|
||||
|
||||
#endif
|
||||
98
src/client/uiprogressrect.cpp
Normal file
98
src/client/uiprogressrect.cpp
Normal file
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
* Copyright (c) 2010-2013 OTClient <https://github.com/edubart/otclient>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "uiprogressrect.h"
|
||||
#include <framework/otml/otml.h>
|
||||
#include <framework/graphics/graphics.h>
|
||||
#include <framework/graphics/fontmanager.h>
|
||||
|
||||
UIProgressRect::UIProgressRect()
|
||||
{
|
||||
m_percent = 0;
|
||||
}
|
||||
|
||||
void UIProgressRect::drawSelf(Fw::DrawPane drawPane)
|
||||
{
|
||||
if((drawPane & Fw::ForegroundPane) == 0)
|
||||
return;
|
||||
|
||||
g_painter->setColor(m_backgroundColor);
|
||||
|
||||
// todo: check +1 to right/bottom
|
||||
// todo: add smooth
|
||||
Rect drawRect = getPaddingRect();
|
||||
|
||||
// 0% - 12.5% (12.5)
|
||||
// triangle from top center, to top right (var x)
|
||||
if(m_percent < 12.5) {
|
||||
Point var = Point(std::max(m_percent - 0.0, 0.0) * (drawRect.right() - drawRect.horizontalCenter()) / 12.5, 0);
|
||||
g_painter->drawFilledTriangle(drawRect.center(), drawRect.topRight() + Point(1,0), drawRect.topCenter() + var);
|
||||
}
|
||||
|
||||
// 12.5% - 37.5% (25)
|
||||
// triangle from top right to bottom right (var y)
|
||||
if(m_percent < 37.5) {
|
||||
Point var = Point(0, std::max(m_percent - 12.5, 0.0) * (drawRect.bottom() - drawRect.top()) / 25.0);
|
||||
g_painter->drawFilledTriangle(drawRect.center(), drawRect.bottomRight() + Point(1,1), drawRect.topRight() + var + Point(1,0));
|
||||
}
|
||||
|
||||
// 37.5% - 62.5% (25)
|
||||
// triangle from bottom right to bottom left (var x)
|
||||
if(m_percent < 62.5) {
|
||||
Point var = Point(std::max(m_percent - 37.5, 0.0) * (drawRect.right() - drawRect.left()) / 25.0, 0);
|
||||
g_painter->drawFilledTriangle(drawRect.center(), drawRect.bottomLeft() + Point(0,1), drawRect.bottomRight() - var + Point(1,1));
|
||||
}
|
||||
|
||||
// 62.5% - 87.5% (25)
|
||||
// triangle from bottom left to top left
|
||||
if(m_percent < 87.5) {
|
||||
Point var = Point(0, std::max(m_percent - 62.5, 0.0) * (drawRect.bottom() - drawRect.top()) / 25.0);
|
||||
g_painter->drawFilledTriangle(drawRect.center(), drawRect.topLeft(), drawRect.bottomLeft() - var + Point(0,1));
|
||||
}
|
||||
|
||||
// 87.5% - 100% (12.5)
|
||||
// triangle from top left to top center
|
||||
if(m_percent < 100) {
|
||||
Point var = Point(std::max(m_percent - 87.5, 0.0) * (drawRect.horizontalCenter() - drawRect.left()) / 12.5, 0);
|
||||
g_painter->drawFilledTriangle(drawRect.center(), drawRect.topCenter(), drawRect.topLeft() + var);
|
||||
}
|
||||
|
||||
drawImage(m_rect);
|
||||
drawBorder(m_rect);
|
||||
drawIcon(m_rect);
|
||||
drawText(m_rect);
|
||||
}
|
||||
|
||||
void UIProgressRect::setPercent(float percent)
|
||||
{
|
||||
m_percent = std::max(std::min((double)percent, 100.0), 0.0);
|
||||
}
|
||||
|
||||
void UIProgressRect::onStyleApply(const std::string& styleName, const OTMLNodePtr& styleNode)
|
||||
{
|
||||
UIWidget::onStyleApply(styleName, styleNode);
|
||||
|
||||
for(const OTMLNodePtr& node : styleNode->children()) {
|
||||
if(node->tag() == "percent")
|
||||
setPercent(node->value<float>());
|
||||
}
|
||||
}
|
||||
45
src/client/uiprogressrect.h
Normal file
45
src/client/uiprogressrect.h
Normal file
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright (c) 2010-2013 OTClient <https://github.com/edubart/otclient>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef UIPROGRESSRECT_H
|
||||
#define UIPROGRESSRECT_H
|
||||
|
||||
#include "declarations.h"
|
||||
#include <framework/ui/uiwidget.h>
|
||||
#include "item.h"
|
||||
|
||||
class UIProgressRect : public UIWidget
|
||||
{
|
||||
public:
|
||||
UIProgressRect();
|
||||
void drawSelf(Fw::DrawPane drawPane);
|
||||
|
||||
void setPercent(float percent);
|
||||
float getPercent() { return m_percent; }
|
||||
|
||||
protected:
|
||||
void onStyleApply(const std::string& styleName, const OTMLNodePtr& styleNode);
|
||||
|
||||
float m_percent;
|
||||
};
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user