Otclient 1.0  14/8/2020
thingtype.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2010-2020 OTClient <https://github.com/edubart/otclient>
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a copy
5  * of this software and associated documentation files (the "Software"), to deal
6  * in the Software without restriction, including without limitation the rights
7  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8  * copies of the Software, and to permit persons to whom the Software is
9  * furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in
12  * all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20  * THE SOFTWARE.
21  */
22 
23 #include "thingtype.h"
24 #include "game.h"
25 #include "lightview.h"
26 #include "map.h"
27 #include "spritemanager.h"
28 
35 #include <framework/otml/otml.h>
36 
38 {
39  m_category = ThingInvalidCategory;
40  m_id = 0;
41  m_null = true;
42  m_exactSize = 0;
43  m_realSize = 0;
44  m_animator = nullptr;
45  m_numPatternX = m_numPatternY = m_numPatternZ = 0;
46  m_animationPhases = 0;
47  m_layers = 0;
48  m_elevation = 0;
49  m_opacity = 1.0f;
50  m_countPainterListeningRef = 0;
51 }
52 
54 {
55  for(int i = 0; i < ThingLastAttr; ++i) {
56  if(!hasAttr(static_cast<ThingAttr>(i)))
57  continue;
58 
59  int attr = i;
60  if(g_game.getClientVersion() >= 780) {
61  if(attr == ThingAttrChargeable)
62  attr = ThingAttrWritable;
63  else if(attr >= ThingAttrWritable)
64  attr += 1;
65  } else if(g_game.getClientVersion() >= 1000) {
66  if(attr == ThingAttrNoMoveAnimation)
67  attr = 16;
68  else if(attr >= ThingAttrPickupable)
69  attr += 1;
70  }
71 
72  fin->addU8(attr);
73  switch(attr) {
75  {
76  fin->addU16(m_displacement.x);
77  fin->addU16(m_displacement.y);
78  break;
79  }
80  case ThingAttrLight:
81  {
82  const Light light = m_attribs.get<Light>(attr);
83  fin->addU16(light.intensity);
84  fin->addU16(light.color);
85  break;
86  }
87  case ThingAttrMarket:
88  {
89  MarketData market = m_attribs.get<MarketData>(attr);
90  fin->addU16(market.category);
91  fin->addU16(market.tradeAs);
92  fin->addU16(market.showAs);
93  fin->addString(market.name);
94  fin->addU16(market.restrictVocation);
95  fin->addU16(market.requiredLevel);
96  break;
97  }
98  case ThingAttrUsable:
99  case ThingAttrElevation:
100  case ThingAttrGround:
101  case ThingAttrWritable:
104  case ThingAttrCloth:
105  case ThingAttrLensHelp:
106  fin->addU16(m_attribs.get<uint16>(attr));
107  break;
108  default:
109  break;
110  }
111  }
112  fin->addU8(ThingLastAttr);
113 
114  fin->addU8(m_size.width());
115  fin->addU8(m_size.height());
116 
117  if(m_size.width() > 1 || m_size.height() > 1)
118  fin->addU8(m_realSize);
119 
120  fin->addU8(m_layers);
121  fin->addU8(m_numPatternX);
122  fin->addU8(m_numPatternY);
123  fin->addU8(m_numPatternZ);
124  fin->addU8(m_animationPhases);
125 
127  if(m_animationPhases > 1 && m_animator != nullptr) {
128  m_animator->serialize(fin);
129  }
130  }
131 
132  for(int i : m_spritesIndex) {
134  fin->addU32(i);
135  else
136  fin->addU16(i);
137  }
138 }
139 
140 void ThingType::unserialize(uint16 clientId, ThingCategory category, const FileStreamPtr& fin)
141 {
142  m_null = false;
143  m_id = clientId;
144  m_category = category;
145 
146  int count = 0, attr = -1;
147  bool done = false;
148  for(int i = 0; i < ThingLastAttr; ++i) {
149  ++count;
150  attr = fin->getU8();
151  if(attr == ThingLastAttr) {
152  done = true;
153  break;
154  }
155 
156  if(g_game.getClientVersion() >= 1000) {
157  /* In 10.10+ all attributes from 16 and up were
158  * incremented by 1 to make space for 16 as
159  * "No Movement Animation" flag.
160  */
161  if(attr == 16)
163  else if(attr > 16)
164  attr -= 1;
165  } else if(g_game.getClientVersion() >= 860) {
166  /* Default attribute values follow
167  * the format of 8.6-9.86.
168  * Therefore no changes here.
169  */
170  } else if(g_game.getClientVersion() >= 780) {
171  /* In 7.80-8.54 all attributes from 8 and higher were
172  * incremented by 1 to make space for 8 as
173  * "Item Charges" flag.
174  */
175  if(attr == 8) {
176  m_attribs.set(ThingAttrChargeable, true);
177  continue;
178  }
179  if(attr > 8)
180  attr -= 1;
181  } else if(g_game.getClientVersion() >= 755) {
182  /* In 7.55-7.72 attributes 23 is "Floor Change". */
183  if(attr == 23)
184  attr = ThingAttrFloorChange;
185  } else if(g_game.getClientVersion() >= 740) {
186  /* In 7.4-7.5 attribute "Ground Border" did not exist
187  * attributes 1-15 have to be adjusted.
188  * Several other changes in the format.
189  */
190  if(attr > 0 && attr <= 15)
191  attr += 1;
192  else if(attr == 16)
193  attr = ThingAttrLight;
194  else if(attr == 17)
195  attr = ThingAttrFloorChange;
196  else if(attr == 18)
197  attr = ThingAttrFullGround;
198  else if(attr == 19)
199  attr = ThingAttrElevation;
200  else if(attr == 20)
201  attr = ThingAttrDisplacement;
202  else if(attr == 22)
203  attr = ThingAttrMinimapColor;
204  else if(attr == 23)
205  attr = ThingAttrRotateable;
206  else if(attr == 24)
207  attr = ThingAttrLyingCorpse;
208  else if(attr == 25)
209  attr = ThingAttrHangable;
210  else if(attr == 26)
211  attr = ThingAttrHookSouth;
212  else if(attr == 27)
213  attr = ThingAttrHookEast;
214  else if(attr == 28)
215  attr = ThingAttrAnimateAlways;
216 
217  /* "Multi Use" and "Force Use" are swapped */
218  if(attr == ThingAttrMultiUse)
219  attr = ThingAttrForceUse;
220  else if(attr == ThingAttrForceUse)
221  attr = ThingAttrMultiUse;
222  }
223 
224  switch(attr) {
226  {
227  if(g_game.getClientVersion() >= 755) {
228  m_displacement.x = fin->getU16();
229  m_displacement.y = fin->getU16();
230  } else {
231  m_displacement.x = 8;
232  m_displacement.y = 8;
233  }
234  m_attribs.set(attr, true);
235  break;
236  }
237  case ThingAttrLight:
238  {
239  Light light;
240  light.intensity = fin->getU16();
241  light.color = fin->getU16();
242  m_attribs.set(attr, light);
243  break;
244  }
245  case ThingAttrMarket:
246  {
247  MarketData market;
248  market.category = fin->getU16();
249  market.tradeAs = fin->getU16();
250  market.showAs = fin->getU16();
251  market.name = fin->getString();
252  market.restrictVocation = fin->getU16();
253  market.requiredLevel = fin->getU16();
254  m_attribs.set(attr, market);
255  break;
256  }
257  case ThingAttrElevation:
258  {
259  m_elevation = fin->getU16();
260  m_attribs.set(attr, m_elevation);
261  break;
262  }
263  case ThingAttrUsable:
264  case ThingAttrGround:
265  case ThingAttrWritable:
268  case ThingAttrCloth:
269  case ThingAttrLensHelp:
270  m_attribs.set(attr, fin->getU16());
271  break;
272  default:
273  m_attribs.set(attr, true);
274  break;
275  }
276  }
277 
278  if(!done)
279  stdext::throw_exception(stdext::format("corrupt data (id: %d, category: %d, count: %d, lastAttr: %d)",
280  m_id, m_category, count, attr));
281 
282  const bool hasFrameGroups = category == ThingCategoryCreature && g_game.getFeature(Otc::GameIdleAnimations);
283  const uint8 groupCount = hasFrameGroups ? fin->getU8() : 1;
284 
285  m_animationPhases = 0;
286  int totalSpritesCount = 0;
287 
288  std::vector<Size> sizes;
289  std::vector<int> total_sprites;
290 
291  for(int i = 0; i < groupCount; ++i) {
292  uint8 frameGroupType = FrameGroupDefault;
293  if(hasFrameGroups)
294  frameGroupType = fin->getU8();
295 
296  const uint8 width = fin->getU8();
297  const uint8 height = fin->getU8();
298  m_size = Size(width, height);
299  sizes.push_back(m_size);
300  if(width > 1 || height > 1) {
301  m_realSize = fin->getU8();
302  m_exactSize = std::min<int>(m_realSize, std::max<int>(width * 32, height * 32));
303  } else
304  m_exactSize = 32;
305 
306  m_layers = fin->getU8();
307  m_numPatternX = fin->getU8();
308  m_numPatternY = fin->getU8();
309  if(g_game.getClientVersion() >= 755)
310  m_numPatternZ = fin->getU8();
311  else
312  m_numPatternZ = 1;
313 
314  const int groupAnimationsPhases = fin->getU8();
315  m_animationPhases += groupAnimationsPhases;
316 
317  if(groupAnimationsPhases > 1 && g_game.getFeature(Otc::GameEnhancedAnimations)) {
318  AnimatorPtr animator = AnimatorPtr(new Animator);
319  animator->unserialize(groupAnimationsPhases, fin);
320 
321  if(groupCount == 1 || frameGroupType == FrameGroupMoving)
322  m_animator = animator;
323  else m_idleAnimator = animator;
324  }
325 
326  const int totalSprites = m_size.area() * m_layers * m_numPatternX * m_numPatternY * m_numPatternZ * groupAnimationsPhases;
327  total_sprites.push_back(totalSprites);
328 
329  if(totalSpritesCount + totalSprites > 4096)
330  stdext::throw_exception("a thing type has more than 4096 sprites");
331 
332  m_spritesIndex.resize(totalSpritesCount + totalSprites);
333  for(int j = totalSpritesCount; j < (totalSpritesCount + totalSprites); ++j)
334  m_spritesIndex[j] = g_game.getFeature(Otc::GameSpritesU32) ? fin->getU32() : fin->getU16();
335 
336  totalSpritesCount += totalSprites;
337  }
338 
339  if(sizes.size() > 1) {
340  // correction for some sprites
341  for(auto& s : sizes) {
342  m_size.setWidth(std::max<int>(m_size.width(), s.width()));
343  m_size.setHeight(std::max<int>(m_size.height(), s.height()));
344  }
345  size_t expectedSize = m_size.area() * m_layers * m_numPatternX * m_numPatternY * m_numPatternZ * m_animationPhases;
346  if(expectedSize != m_spritesIndex.size()) {
347  std::vector<int> sprites(std::move(m_spritesIndex));
348  m_spritesIndex.clear();
349  m_spritesIndex.reserve(expectedSize);
350  for(size_t i = 0, idx = 0; i < sizes.size(); ++i) {
351  int totalSprites = total_sprites[i];
352  if(m_size == sizes[i]) {
353  for(int j = 0; j < totalSprites; ++j) {
354  m_spritesIndex.push_back(sprites[idx++]);
355  }
356  continue;
357  }
358  size_t patterns = (totalSprites / sizes[i].area());
359  for(size_t p = 0; p < patterns; ++p) {
360  for(int x = 0; x < m_size.width(); ++x) {
361  for(int y = 0; y < m_size.height(); ++y) {
362  if(x < sizes[i].width() && y < sizes[i].height()) {
363  m_spritesIndex.push_back(sprites[idx++]);
364  continue;
365  }
366  m_spritesIndex.push_back(0);
367  }
368  }
369  }
370  }
371  }
372  }
373 
374  m_textures.resize(m_animationPhases);
375  m_texturesFramesRects.resize(m_animationPhases);
376  m_texturesFramesOriginRects.resize(m_animationPhases);
377  m_texturesFramesOffsets.resize(m_animationPhases);
378 }
379 
380 void ThingType::exportImage(const std::string& fileName)
381 {
382  if(m_null)
383  stdext::throw_exception("cannot export null thingtype");
384 
385  if(m_spritesIndex.empty())
386  stdext::throw_exception("cannot export thingtype without sprites");
387 
388  ImagePtr image(new Image(Size(32 * m_size.width() * m_layers * m_numPatternX, 32 * m_size.height() * m_animationPhases * m_numPatternY * m_numPatternZ)));
389  for(int z = 0; z < m_numPatternZ; ++z) {
390  for(int y = 0; y < m_numPatternY; ++y) {
391  for(int x = 0; x < m_numPatternX; ++x) {
392  for(int l = 0; l < m_layers; ++l) {
393  for(int a = 0; a < m_animationPhases; ++a) {
394  for(int w = 0; w < m_size.width(); ++w) {
395  for(int h = 0; h < m_size.height(); ++h) {
396  image->blit(Point(32 * (m_size.width() - w - 1 + m_size.width() * x + m_size.width() * m_numPatternX * l),
397  32 * (m_size.height() - h - 1 + m_size.height() * y + m_size.height() * m_numPatternY * a + m_size.height() * m_numPatternY * m_animationPhases * z)),
398  g_sprites.getSpriteImage(m_spritesIndex[getSpriteIndex(w, h, l, x, y, z, a)]));
399  }
400  }
401  }
402  }
403  }
404  }
405  }
406 
407  image->savePNG(fileName);
408 }
409 
411 {
412  for(const OTMLNodePtr& node2 : node->children()) {
413  if(node2->tag() == "opacity")
414  m_opacity = node2->value<float>();
415  else if(node2->tag() == "notprewalkable")
416  m_attribs.set(ThingAttrNotPreWalkable, node2->value<bool>());
417  else if(node2->tag() == "image")
418  m_customImage = node2->value();
419  else if(node2->tag() == "full-ground") {
420  if(node2->value<bool>())
421  m_attribs.set(ThingAttrFullGround, true);
422  else
423  m_attribs.remove(ThingAttrFullGround);
424  }
425  }
426 }
427 
428 void ThingType::draw(const Point& dest, float scaleFactor, int layer, int xPattern, int yPattern, int zPattern, int animationPhase, int reDrawFlags, LightView* lightView)
429 {
430  if(m_null)
431  return;
432 
433  if(animationPhase >= m_animationPhases)
434  return;
435 
436  const TexturePtr& texture = getTexture(animationPhase); // texture might not exists, neither its rects.
437  if(!texture)
438  return;
439 
440  const uint frameIndex = getTextureIndex(layer, xPattern, yPattern, zPattern);
441  if(frameIndex >= m_texturesFramesRects[animationPhase].size())
442  return;
443 
444  Point textureOffset;
445  Rect textureRect;
446 
447  if(scaleFactor != 1.0f) {
448  textureRect = m_texturesFramesOriginRects[animationPhase][frameIndex];
449  } else {
450  textureOffset = m_texturesFramesOffsets[animationPhase][frameIndex];
451  textureRect = m_texturesFramesRects[animationPhase][frameIndex];
452  }
453 
454  const Rect screenRect(dest + (textureOffset - m_displacement - (m_size.toPoint() - Point(1, 1)) * 32) * scaleFactor,
455  textureRect.size() * scaleFactor);
456 
457  if(reDrawFlags & Otc::ReDrawThing) {
458  const bool useOpacity = m_opacity < 1.0f;
459 
460  if(useOpacity)
461  g_painter->setColor(Color(1.0f, 1.0f, 1.0f, m_opacity));
462 
463  g_painter->drawTexturedRect(screenRect, texture, textureRect);
464 
465  if(useOpacity)
467  }
468 
469  if(lightView && hasLight() && reDrawFlags & Otc::ReDrawLight) {
470  const Light light = getLight();
471  if(light.intensity > 0)
472  lightView->addLightSource(screenRect.center(), scaleFactor, light);
473  }
474 }
475 
476 const TexturePtr& ThingType::getTexture(int animationPhase)
477 {
478  TexturePtr& animationPhaseTexture = m_textures[animationPhase];
479  if(animationPhaseTexture) return animationPhaseTexture;
480 
481  bool useCustomImage = false;
482  if(animationPhase == 0 && !m_customImage.empty())
483  useCustomImage = true;
484 
485  // we don't need layers in common items, they will be pre-drawn
486  int textureLayers = 1;
487  int numLayers = m_layers;
488  if(m_category == ThingCategoryCreature && numLayers >= 2) {
489  // 5 layers: outfit base, red mask, green mask, blue mask, yellow mask
490  textureLayers = 5;
491  numLayers = 5;
492  }
493 
494  const int indexSize = textureLayers * m_numPatternX * m_numPatternY * m_numPatternZ;
495  const Size textureSize = getBestTextureDimension(m_size.width(), m_size.height(), indexSize);
496  const ImagePtr fullImage = useCustomImage ? Image::load(m_customImage) : ImagePtr(new Image(textureSize * Otc::TILE_PIXELS));
497 
498  m_texturesFramesRects[animationPhase].resize(indexSize);
499  m_texturesFramesOriginRects[animationPhase].resize(indexSize);
500  m_texturesFramesOffsets[animationPhase].resize(indexSize);
501  for(int z = 0; z < m_numPatternZ; ++z) {
502  for(int y = 0; y < m_numPatternY; ++y) {
503  for(int x = 0; x < m_numPatternX; ++x) {
504  for(int l = 0; l < numLayers; ++l) {
505  const bool spriteMask = m_category == ThingCategoryCreature && l > 0;
506  const int frameIndex = getTextureIndex(l % textureLayers, x, y, z);
507 
508  Point framePos = Point(frameIndex % (textureSize.width() / m_size.width()) * m_size.width(),
509  frameIndex / (textureSize.width() / m_size.width()) * m_size.height()) * Otc::TILE_PIXELS;
510 
511  if(!useCustomImage) {
512  for(int h = 0; h < m_size.height(); ++h) {
513  for(int w = 0; w < m_size.width(); ++w) {
514  const uint spriteIndex = getSpriteIndex(w, h, spriteMask ? 1 : l, x, y, z, animationPhase);
515  ImagePtr spriteImage = g_sprites.getSpriteImage(m_spritesIndex[spriteIndex]);
516  if(!spriteImage) fullImage->setTransparentPixel(true);
517  else {
518  if(spriteIndex == 0) {
519  if(spriteImage->hasTransparentPixel() || hasDisplacement()) {
520  fullImage->setTransparentPixel(true);
521  }
522  }
523  if(spriteMask) {
524  static Color maskColors[] = { Color::red, Color::green, Color::blue, Color::yellow };
525  spriteImage->overwriteMask(maskColors[l - 1]);
526  }
527  Point spritePos = Point(m_size.width() - w - 1,
528  m_size.height() - h - 1) * Otc::TILE_PIXELS;
529 
530  fullImage->blit(framePos + spritePos, spriteImage);
531  }
532  }
533  }
534  }
535 
536  Rect drawRect(framePos + Point(m_size.width(), m_size.height()) * Otc::TILE_PIXELS - Point(1, 1), framePos);
537  for(int fx = framePos.x; fx < framePos.x + m_size.width() * Otc::TILE_PIXELS; ++fx) {
538  for(int fy = framePos.y; fy < framePos.y + m_size.height() * Otc::TILE_PIXELS; ++fy) {
539  uint8* p = fullImage->getPixel(fx, fy);
540  if(p[3] != 0x00) {
541  drawRect.setTop(std::min<int>(fy, static_cast<int>(drawRect.top())));
542  drawRect.setLeft(std::min<int>(fx, static_cast<int>(drawRect.left())));
543  drawRect.setBottom(std::max<int>(fy, static_cast<int>(drawRect.bottom())));
544  drawRect.setRight(std::max<int>(fx, static_cast<int>(drawRect.right())));
545  }
546  }
547  }
548 
549  m_texturesFramesRects[animationPhase][frameIndex] = drawRect;
550  m_texturesFramesOriginRects[animationPhase][frameIndex] = Rect(framePos, Size(m_size.width(), m_size.height()) * Otc::TILE_PIXELS);
551  m_texturesFramesOffsets[animationPhase][frameIndex] = drawRect.topLeft() - framePos;
552  }
553  }
554  }
555  }
556 
557  animationPhaseTexture = TexturePtr(new Texture(fullImage, true));
558  animationPhaseTexture->setSmooth(true);
559 
560  return animationPhaseTexture;
561 }
562 
563 Size ThingType::getBestTextureDimension(int w, int h, int count)
564 {
565  const int MAX = 32;
566 
567  int k = 1;
568  while(k < w)
569  k <<= 1;
570  w = k;
571 
572  k = 1;
573  while(k < h)
574  k <<= 1;
575  h = k;
576 
577  const int numSprites = w * h * count;
578  assert(numSprites <= MAX * MAX);
579  assert(w <= MAX);
580  assert(h <= MAX);
581 
582  Size bestDimension = Size(MAX, MAX);
583  for(int i = w; i <= MAX; i <<= 1) {
584  for(int j = h; j <= MAX; j <<= 1) {
585  Size candidateDimension = Size(i, j);
586  if(candidateDimension.area() < numSprites)
587  continue;
588  if((candidateDimension.area() < bestDimension.area()) ||
589  (candidateDimension.area() == bestDimension.area() && candidateDimension.width() + candidateDimension.height() < bestDimension.width() + bestDimension.height()))
590  bestDimension = candidateDimension;
591  }
592  }
593 
594  return bestDimension;
595 }
596 
597 uint ThingType::getSpriteIndex(int w, int h, int l, int x, int y, int z, int a)
598 {
599  const uint index =
600  ((((((a % m_animationPhases)
601  * m_numPatternZ + z)
602  * m_numPatternY + y)
603  * m_numPatternX + x)
604  * m_layers + l)
605  * m_size.height() + h)
606  * m_size.width() + w;
607  assert(index < m_spritesIndex.size());
608  return index;
609 }
610 
611 uint ThingType::getTextureIndex(int l, int x, int y, int z)
612 {
613  return ((l * m_numPatternZ + z)
614  * m_numPatternY + y)
615  * m_numPatternX + x;
616 }
617 
618 int ThingType::getExactSize(int layer, int xPattern, int yPattern, int zPattern, int animationPhase)
619 {
620  if(m_null)
621  return 0;
622 
623  getTexture(animationPhase); // we must calculate it anyway.
624  const int frameIndex = getTextureIndex(layer, xPattern, yPattern, zPattern);
625  const Size size = m_texturesFramesOriginRects[animationPhase][frameIndex].size() - m_texturesFramesOffsets[animationPhase][frameIndex].toSize();
626  return std::max<int>(size.width(), size.height());
627 }
628 
630 {
631  if(var == true)
632  m_attribs.remove(ThingAttrNotPathable);
633  else
634  m_attribs.set(ThingAttrNotPathable, true);
635 }
636 
638 {
639  if(m_animator) return m_animator->getAnimationPhases();
640 
641  if(m_category == ThingCategoryCreature) return m_animationPhases - 1;
642 
643  return m_animationPhases;
644 }
645 
647 {
648  if(m_null)
649  return 0;
650 
651  if(m_exactHeight != -1)
652  return m_exactHeight;
653 
654  getTexture(0);
655  const int frameIndex = getTextureIndex(0, 0, 0, 0);
656  const Size size = m_texturesFramesOriginRects[0][frameIndex].size() - m_texturesFramesOffsets[0][frameIndex].toSize();
657 
658  return m_exactHeight = size.height();
659 }
660 
661 void ThingType::startListenerPainter(const float duration)
662 {
663  if(m_countPainterListeningRef == 0) {
664  m_painterListeningEvent = g_dispatcher.cycleEvent([=]() {
665  uint32_t redrawFlag = Otc::ReDrawThing;
666 
668  redrawFlag |= Otc::ReDrawLight;
669 
670  g_map.requestDrawing(Position(), static_cast<Otc::RequestDrawFlags>(redrawFlag));
671  }, duration);
672  }
673 
674  ++m_countPainterListeningRef;
675 }
676 
678 {
679  if(m_countPainterListeningRef == 0) return false;
680 
681  --m_countPainterListeningRef;
682 
683  if(m_painterListeningEvent && m_countPainterListeningRef == 0) {
684  uint32_t redrawFlag = Otc::ReDrawThing;
685  if(hasLight()) redrawFlag |= Otc::ReDrawLight;
686 
687  g_map.requestDrawing(Position(), static_cast<Otc::RequestDrawFlags>(redrawFlag), true);
688 
689  m_painterListeningEvent->cancel();
690  m_painterListeningEvent = nullptr;
691  }
692 
693  return true;
694 }
Painter::setColor
virtual void setColor(const Color &color)
Definition: painter.h:77
ThingAttrNoMoveAnimation
@ ThingAttrNoMoveAnimation
Definition: thingtype.h:99
ThingAttrLyingCorpse
@ ThingAttrLyingCorpse
Definition: thingtype.h:81
Otc::TILE_PIXELS
@ TILE_PIXELS
Definition: const.h:33
Map::requestDrawing
void requestDrawing(const Position &pos, const Otc::RequestDrawFlags reDrawFlags, const bool force=false, const bool isLocalPlayer=false)
Definition: map.cpp:84
lightview.h
eventdispatcher.h
MarketData::requiredLevel
uint16 requiredLevel
Definition: thingtype.h:114
graphics.h
g_map
Map g_map
Definition: map.cpp:36
ThingAttrFullGround
@ ThingAttrFullGround
Definition: thingtype.h:85
Color
Definition: color.h:32
ThingCategoryMissile
@ ThingCategoryMissile
Definition: thingtype.h:49
TPoint::y
T y
Definition: point.h:83
z
gc sort z
Definition: CMakeLists.txt:176
ThingType::cancelListenerPainter
bool cancelListenerPainter()
Definition: thingtype.cpp:677
TSize::setWidth
void setWidth(T w)
Definition: size.h:47
otml.h
ThingAttrHookEast
@ ThingAttrHookEast
Definition: thingtype.h:74
TRect< int >
FileStream::addU32
void addU32(uint32 v)
Definition: filestream.cpp:377
Image::load
static ImagePtr load(std::string file)
Definition: image.cpp:40
ThingAttrGround
@ ThingAttrGround
Definition: thingtype.h:55
Animator::unserialize
void unserialize(int animationPhases, const FileStreamPtr &fin)
Definition: animator.cpp:43
g_dispatcher
EventDispatcher g_dispatcher
Definition: eventdispatcher.cpp:28
FrameGroupDefault
@ FrameGroupDefault
Definition: thingtype.h:40
Texture
Definition: texture.h:28
ThingAttrMinimapColor
@ ThingAttrMinimapColor
Definition: thingtype.h:83
ThingAttrHangable
@ ThingAttrHangable
Definition: thingtype.h:72
LightView::addLightSource
void addLightSource(const Point &center, float scaleFactor, const Light &light)
Definition: lightview.cpp:80
ThingAttrChargeable
@ ThingAttrChargeable
Definition: thingtype.h:100
ThingType::startListenerPainter
void startListenerPainter(float duration)
Definition: thingtype.cpp:661
ThingAttrUsable
@ ThingAttrUsable
Definition: thingtype.h:89
TRect::left
T left() const
Definition: rect.h:52
Otc::GameEnhancedAnimations
@ GameEnhancedAnimations
Definition: const.h:424
TSize::area
T area() const
Definition: size.h:101
ThingAttrRotateable
@ ThingAttrRotateable
Definition: thingtype.h:75
ThingAttrWritableOnce
@ ThingAttrWritableOnce
Definition: thingtype.h:64
ThingAttrWritable
@ ThingAttrWritable
Definition: thingtype.h:63
ThingType::ThingType
ThingType()
Definition: thingtype.cpp:37
Game::getClientVersion
int getClientVersion()
Definition: game.h:318
texturemanager.h
Animator::getAnimationPhases
int getAnimationPhases()
Definition: animator.h:56
ThingType::hasLight
bool hasLight()
Definition: thingtype.h:191
TRect::setTop
void setTop(T pos)
Definition: rect.h:76
MarketData::category
int category
Definition: thingtype.h:113
ThingAttrFloorChange
@ ThingAttrFloorChange
Definition: thingtype.h:98
Otc::GameIdleAnimations
@ GameIdleAnimations
Definition: const.h:436
OTMLNode::children
OTMLNodeList children()
Definition: otmlnode.cpp:171
Otc::ReDrawThing
@ ReDrawThing
Definition: const.h:56
TRect::bottom
T bottom() const
Definition: rect.h:55
ThingType::unserializeOtml
void unserializeOtml(const OTMLNodePtr &node)
Definition: thingtype.cpp:410
ThingType::getLight
Light getLight()
Definition: thingtype.h:164
g_game
Game g_game
Definition: game.cpp:37
Point
TPoint< int > Point
Definition: point.h:86
Animator::serialize
void serialize(const FileStreamPtr &fin)
Definition: animator.cpp:62
Otc::ReDrawLight
@ ReDrawLight
Definition: const.h:57
FileStream::getString
std::string getString()
Definition: filestream.cpp:309
SpriteManager::getSpriteImage
ImagePtr getSpriteImage(int id)
Definition: spritemanager.cpp:127
ThingAttrDisplacement
@ ThingAttrDisplacement
Definition: thingtype.h:79
TRect::setLeft
void setLeft(T pos)
Definition: rect.h:75
stdext::format
std::string format()
Definition: format.h:84
ThingAttrCloth
@ ThingAttrCloth
Definition: thingtype.h:87
Otc::RequestDrawFlags
RequestDrawFlags
Definition: const.h:55
ThingType::getAnimationPhases
int getAnimationPhases()
Definition: thingtype.cpp:637
ImagePtr
stdext::shared_object_ptr< Image > ImagePtr
Definition: declarations.h:46
TSize::width
int width() const
Definition: size.h:43
ThingInvalidCategory
@ ThingInvalidCategory
Definition: thingtype.h:50
LightView
Definition: lightview.h:37
FileStream::addString
void addString(const std::string &v)
Definition: filestream.cpp:448
uint16
uint16_t uint16
Definition: types.h:36
ThingType::serialize
void serialize(const FileStreamPtr &fin)
Definition: thingtype.cpp:53
Otc::GameSpritesU32
@ GameSpritesU32
Definition: const.h:385
ThingType::hasAttr
bool hasAttr(ThingAttr attr)
Definition: thingtype.h:142
Color::green
static const Color green
Definition: color.h:105
Image
Definition: image.h:29
ThingType::getTexture
const TexturePtr & getTexture(int animationPhase)
Definition: thingtype.cpp:476
TRect::setRight
void setRight(T pos)
Definition: rect.h:77
ThingType::unserialize
void unserialize(uint16 clientId, ThingCategory category, const FileStreamPtr &fin)
Definition: thingtype.cpp:140
TRect::topLeft
TPoint< T > topLeft() const
Definition: rect.h:60
Light::intensity
uint8 intensity
Definition: thingtype.h:122
ThingAttrMultiUse
@ ThingAttrMultiUse
Definition: thingtype.h:62
stdext::dynamic_storage::set
void set(const Key &k, const T &value)
Definition: dynamic_storage.h:35
EventDispatcher::cycleEvent
ScheduledEventPtr cycleEvent(const std::function< void()> &callback, int delay)
Definition: eventdispatcher.cpp:93
uint
unsigned int uint
Definition: types.h:31
TSize::setHeight
void setHeight(T h)
Definition: size.h:48
ThingCategoryCreature
@ ThingCategoryCreature
Definition: thingtype.h:47
FileStream::getU16
uint16 getU16()
Definition: filestream.cpp:199
g_sprites
SpriteManager g_sprites
Definition: spritemanager.cpp:29
spritemanager.h
ThingAttrNotPathable
@ ThingAttrNotPathable
Definition: thingtype.h:70
Position
Definition: position.h:33
Color::white
static const Color white
Definition: color.h:101
MarketData::tradeAs
uint16 tradeAs
Definition: thingtype.h:117
image.h
Size
TSize< int > Size
Definition: size.h:107
map.h
TPoint::x
T x
Definition: point.h:83
Game::getFeature
bool getFeature(Otc::GameFeature feature)
Definition: game.h:312
ThingAttr
ThingAttr
Definition: thingtype.h:54
TexturePtr
stdext::shared_object_ptr< Texture > TexturePtr
Definition: declarations.h:49
MarketData::showAs
uint16 showAs
Definition: thingtype.h:116
Color::blue
static const Color blue
Definition: color.h:107
stdext::dynamic_storage::get
T get(const Key &k) const
Definition: dynamic_storage.h:48
stdext::throw_exception
void throw_exception(const std::string &what)
Throws a generic exception.
Definition: exception.h:43
Rect
TRect< int > Rect
Definition: rect.h:319
FrameGroupMoving
@ FrameGroupMoving
Definition: thingtype.h:42
ThingAttrElevation
@ ThingAttrElevation
Definition: thingtype.h:80
filestream.h
ThingType::getExactHeight
int getExactHeight()
Definition: thingtype.cpp:646
TSize::height
int height() const
Definition: size.h:44
TRect::right
T right() const
Definition: rect.h:54
ThingLastAttr
@ ThingLastAttr
Definition: thingtype.h:101
texture.h
ThingAttrAnimateAlways
@ ThingAttrAnimateAlways
Definition: thingtype.h:82
stdext::dynamic_storage::remove
bool remove(const Key &k)
Definition: dynamic_storage.h:40
stdext::shared_object_ptr< FileStream >
ThingAttrLight
@ ThingAttrLight
Definition: thingtype.h:76
ThingAttrHookSouth
@ ThingAttrHookSouth
Definition: thingtype.h:73
Texture::setSmooth
virtual void setSmooth(bool smooth)
Definition: texture.cpp:131
ThingType::hasDisplacement
bool hasDisplacement()
Definition: thingtype.h:194
g_painter
Painter * g_painter
Definition: painter.cpp:28
ThingAttrPickupable
@ ThingAttrPickupable
Definition: thingtype.h:71
Light::color
uint8 color
Definition: thingtype.h:123
ThingType::exportImage
void exportImage(const std::string &fileName)
Definition: thingtype.cpp:380
AnimatorPtr
stdext::shared_object_ptr< Animator > AnimatorPtr
Definition: declarations.h:72
MarketData
Definition: thingtype.h:111
Light
Definition: thingtype.h:120
FileStream::getU32
uint32 getU32()
Definition: filestream.cpp:215
Color::red
static const Color red
Definition: color.h:103
TSize::toPoint
TPoint< T > toPoint() const
Definition: size.h:37
TRect::top
T top() const
Definition: rect.h:53
game.h
ThingCategory
ThingCategory
Definition: thingtype.h:45
ThingType::setPathable
void setPathable(bool var)
Definition: thingtype.cpp:629
ThingAttrForceUse
@ ThingAttrForceUse
Definition: thingtype.h:61
MarketData::name
std::string name
Definition: thingtype.h:112
ThingAttrMarket
@ ThingAttrMarket
Definition: thingtype.h:88
TPoint< int >
thingtype.h
TRect::size
TSize< T > size() const
Definition: rect.h:71
ThingType::getCategory
ThingCategory getCategory()
Definition: thingtype.h:140
FileStream::addU8
void addU8(uint8 v)
Definition: filestream.cpp:354
ThingType::draw
void draw(const Point &dest, float scaleFactor, int layer, int xPattern, int yPattern, int zPattern, int animationPhase, int reDrawFlags=Otc::ReDrawThing, LightView *lightView=nullptr)
Definition: thingtype.cpp:428
MarketData::restrictVocation
uint16 restrictVocation
Definition: thingtype.h:115
TRect::center
TPoint< T > center() const
Definition: rect.h:68
Event::cancel
void cancel()
Definition: event.cpp:49
ThingAttrNotPreWalkable
@ ThingAttrNotPreWalkable
Definition: thingtype.h:96
Animator
Definition: animator.h:43
TSize< int >
ThingAttrLensHelp
@ ThingAttrLensHelp
Definition: thingtype.h:84
FileStream::getU8
uint8 getU8()
Definition: filestream.cpp:183
ThingType::getExactSize
int getExactSize(int layer=0, int xPattern=0, int yPattern=0, int zPattern=0, int animationPhase=0)
Definition: thingtype.cpp:618
uint8
uint8_t uint8
Definition: types.h:37
Color::yellow
static const Color yellow
Definition: color.h:111
Painter::drawTexturedRect
virtual void drawTexturedRect(const Rect &dest, const TexturePtr &texture, const Rect &src)=0
TRect::setBottom
void setBottom(T pos)
Definition: rect.h:78
FileStream::addU16
void addU16(uint16 v)
Definition: filestream.cpp:365