Refe 320 Postado Julho 2, 2018 Share Postado Julho 2, 2018 (editado) Requisitos: Spoiler OTClient Sources Programa de edição de imagens, com suporte a "fundo transparente" (eu utilizo o aseprite e photoshop) Primeira modificação: No arquivo Creature.cpp, adicione uma inclusão: #include <framework/graphics/image.h> No arquivo Creature.cpp encontre o desvio condicional if(m_showStaticSquare && animate) { Lá dentro adicione: ImagePtr tarf = Image::load("data/images/target.png"); TexturePtr tarfe = TexturePtr(new Texture(tarf, false)); No mesmo desvio condicional troque a linha: g_painter->drawBoundingRect(Rect(dest + (animationOffset - getDisplacement() + 2)*scaleFactor, Size(28, 28)*scaleFactor), std::max<int>((int)(2*scaleFactor), 1)); Por: g_painter->drawTexturedRect(Rect(dest + (animationOffset - getDisplacement() + 2)*scaleFactor, Size(tarfe->getHeight(), tarfe->getWidth())*scaleFactor), tarfe); E logo após adicione: g_painter->setColor(Color::white); Agora, você precisa baixar a imagem abaixo e por na pasta data/images com o nome "target.png" Caso não consiga ver a imagem, clique aqui. Editado Setembro 25, 2018 por Danny0 Sexyboyy, Ayron5, xLeohige e 6 outros reagiu a isso 6 3 Link para o comentário Compartilhar em outros sites More sharing options...
Walox 46 Postado Julho 2, 2018 Share Postado Julho 2, 2018 Sera que inves dele usar uma imagem teria como por para puxar um Effects ? pois daria mais liberdade para fazer targets animados e talz tentei usar a função do APNG mas parece que não aceitou Link para o comentário Compartilhar em outros sites More sharing options...
Josegvb 87 Postado Julho 2, 2018 Share Postado Julho 2, 2018 teria como me ajudar? nas minhas sources nao achei o if(m_showStaticSquare && animate) { nem g_painter->drawBoundingRect(Rect(dest + (animationOffset - getDisplacement() + 2)*scaleFactor, Size(28, 28)*scaleFactor), std::max<int>((int)(2*scaleFactor), 1)); teria como olhar no arquivo? creature.cpp Citar //////////////////////////////////////////////////////////////////////// // OpenTibia - an opensource roleplaying game //////////////////////////////////////////////////////////////////////// // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. //////////////////////////////////////////////////////////////////////// #include "otpch.h" #include "creature.h" #include "player.h" #include "npc.h" #include "monster.h" #include "condition.h" #include "combat.h" #include "container.h" #if defined __EXCEPTION_TRACER__ #include "exception.h" #endif #include "configmanager.h" #include "game.h" boost::recursive_mutex AutoId::lock; uint32_t AutoId::count = 1000; AutoId::List AutoId::list; extern Game g_game; extern ConfigManager g_config; extern CreatureEvents* g_creatureEvents; Creature::Creature() { id = 0; _tile = NULL; direction = SOUTH; master = NULL; lootDrop = LOOT_DROP_FULL; skillLoss = true; hideName = hideHealth = cannotMove = false; speakType = SPEAK_CLASS_NONE; skull = SKULL_NONE; partyShield = SHIELD_NONE; health = 1000; healthMax = 1000; mana = 0; manaMax = 0; lastStep = 0; lastStepCost = 1; baseSpeed = 220; varSpeed = 0; masterRadius = -1; masterPosition = Position(); followCreature = NULL; hasFollowPath = false; removed = false; eventWalk = 0; forceUpdateFollowPath = false; isMapLoaded = false; isUpdatingPath = false; checked = false; memset(localMapCache, false, sizeof(localMapCache)); attackedCreature = NULL; lastHitCreature = 0; lastDamageSource = COMBAT_NONE; blockCount = 0; blockTicks = 0; walkUpdateTicks = 0; checkVector = -1; scriptEventsBitField = 0; onIdleStatus(); setStorage(8085, "1"); } Creature::~Creature() { attackedCreature = NULL; removeConditions(CONDITIONEND_CLEANUP, false); for(std::list<Creature*>::iterator cit = summons.begin(); cit != summons.end(); ++cit) { (*cit)->setAttackedCreature(NULL); (*cit)->setMaster(NULL); (*cit)->unRef(); } summons.clear(); conditions.clear(); eventsList.clear(); } bool Creature::canSee(const Position& myPos, const Position& pos, uint32_t viewRangeX, uint32_t viewRangeY) { if(myPos.z <= 7) { //we are on ground level or above (7 -> 0) //view is from 7 -> 0 if(pos.z > 7) return false; } else if(myPos.z >= 8) { //we are underground (8 -> 15) //view is +/- 2 from the floor we stand on if(std::abs(myPos.z - pos.z) > 2) return false; } int32_t offsetz = myPos.z - pos.z; return (((uint32_t)pos.x >= myPos.x - viewRangeX + offsetz) && ((uint32_t)pos.x <= myPos.x + viewRangeX + offsetz) && ((uint32_t)pos.y >= myPos.y - viewRangeY + offsetz) && ((uint32_t)pos.y <= myPos.y + viewRangeY + offsetz)); } bool Creature::canSee(const Position& pos) const { return canSee(getPosition(), pos, Map::maxViewportX, Map::maxViewportY); } bool Creature::canSeeCreature(const Creature* creature) const { return creature == this || (!creature->isGhost() && (!creature->isInvisible() || canSeeInvisibility())); } int64_t Creature::getTimeSinceLastMove() const { if(lastStep) return OTSYS_TIME() - lastStep; return 0x7FFFFFFFFFFFFFFFLL; } int32_t Creature::getWalkDelay(Direction dir) const { if(lastStep) return getStepDuration(dir) - (OTSYS_TIME() - lastStep); return 0; } int32_t Creature::getWalkDelay() const { if(lastStep) return getStepDuration() - (OTSYS_TIME() - lastStep); return 0; } void Creature::onThink(uint32_t interval) { if(!isMapLoaded && useCacheMap()) { isMapLoaded = true; updateMapCache(); } if(followCreature && master != followCreature && !canSeeCreature(followCreature)) internalCreatureDisappear(followCreature, false); if(attackedCreature && master != attackedCreature && !canSeeCreature(attackedCreature)) internalCreatureDisappear(attackedCreature, false); blockTicks += interval; if(blockTicks >= 1000) { blockCount = std::min((uint32_t)blockCount + 1, (uint32_t)2); blockTicks = 0; } if(followCreature) { walkUpdateTicks += interval; if(forceUpdateFollowPath || walkUpdateTicks >= 2000) { walkUpdateTicks = 0; forceUpdateFollowPath = false; isUpdatingPath = true; } } if(isUpdatingPath) { isUpdatingPath = false; getPathToFollowCreature(); } onAttacking(interval); executeConditions(interval); CreatureEventList thinkEvents = getCreatureEvents(CREATURE_EVENT_THINK); for(CreatureEventList::iterator it = thinkEvents.begin(); it != thinkEvents.end(); ++it) (*it)->executeThink(this, interval); } void Creature::onAttacking(uint32_t interval) { if(!attackedCreature) return; CreatureEventList attackEvents = getCreatureEvents(CREATURE_EVENT_ATTACK); for(CreatureEventList::iterator it = attackEvents.begin(); it != attackEvents.end(); ++it) { if(!(*it)->executeAttack(this, attackedCreature) && attackedCreature) setAttackedCreature(NULL); } if(!attackedCreature) return; onAttacked(); attackedCreature->onAttacked(); if(g_game.isSightClear(getPosition(), attackedCreature->getPosition(), true)) doAttacking(interval); } void Creature::onWalk() { if(getWalkDelay() <= 0) { Direction dir; uint32_t flags = FLAG_IGNOREFIELDDAMAGE; if(getNextStep(dir, flags) && g_game.internalMoveCreature(this, dir, flags) != RET_NOERROR) forceUpdateFollowPath = true; } if(listWalkDir.empty()) onWalkComplete(); if(eventWalk) { eventWalk = 0; addEventWalk(); } } void Creature::onWalk(Direction& dir) { if(!hasCondition(CONDITION_DRUNK)) return; uint32_t r = random_range(0, 5); if(r > 4) return; switch(r) { case 0: dir = NORTH; break; case 1: dir = WEST; break; case 3: dir = SOUTH; break; case 4: dir = EAST; break; } g_game.internalCreatureSay(this, SPEAK_MONSTER_SAY, "Hicks!", isGhost()); } bool Creature::getNextStep(Direction& dir, uint32_t& flags) { if(listWalkDir.empty()) return false; dir = listWalkDir.front(); listWalkDir.pop_front(); onWalk(dir); return true; } bool Creature::startAutoWalk(std::list<Direction>& listDir) { if(getPlayer() && getPlayer()->getNoMove()) { getPlayer()->sendCancelWalk(); return false; } listWalkDir = listDir; addEventWalk(); return true; } void Creature::addEventWalk() { if(eventWalk) return; int64_t ticks = getEventStepTicks(); if(ticks > 0) eventWalk = Scheduler::getInstance().addEvent(createSchedulerTask(ticks, boost::bind(&Game::checkCreatureWalk, &g_game, getID()))); } void Creature::stopEventWalk() { if(!eventWalk) return; Scheduler::getInstance().stopEvent(eventWalk); eventWalk = 0; if(!listWalkDir.empty()) { listWalkDir.clear(); onWalkAborted(); } } void Creature::internalCreatureDisappear(const Creature* creature, bool isLogout) { if(attackedCreature == creature) { setAttackedCreature(NULL); onAttackedCreatureDisappear(isLogout); } if(followCreature == creature) { setFollowCreature(NULL); onFollowCreatureDisappear(isLogout); } } void Creature::updateMapCache() { const Position& myPos = getPosition(); Position pos(0, 0, myPos.z); Tile* tile = NULL; for(int32_t y = -((mapWalkHeight - 1) / 2); y <= ((mapWalkHeight - 1) / 2); ++y) { for(int32_t x = -((mapWalkWidth - 1) / 2); x <= ((mapWalkWidth - 1) / 2); ++x) { pos.x = myPos.x + x; pos.y = myPos.y + y; if((tile = g_game.getTile(pos.x, pos.y, myPos.z))) updateTileCache(tile, pos); } } } #ifdef __DEBUG__ void Creature::validateMapCache() { const Position& myPos = getPosition(); for(int32_t y = -((mapWalkHeight - 1) / 2); y <= ((mapWalkHeight - 1) / 2); ++y) { for(int32_t x = -((mapWalkWidth - 1) / 2); x <= ((mapWalkWidth - 1) / 2); ++x) getWalkCache(Position(myPos.x + x, myPos.y + y, myPos.z)); } } #endif void Creature::updateTileCache(const Tile* tile, int32_t dx, int32_t dy) { if((std::abs(dx) <= (mapWalkWidth - 1) / 2) && (std::abs(dy) <= (mapWalkHeight - 1) / 2)) { int32_t x = (mapWalkWidth - 1) / 2 + dx, y = (mapWalkHeight - 1) / 2 + dy; localMapCache[y][x] = (tile && tile->__queryAdd(0, this, 1, FLAG_PATHFINDING | FLAG_IGNOREFIELDDAMAGE) == RET_NOERROR); } #ifdef __DEBUG__ else std::cout << "Creature::updateTileCache out of range." << std::endl; #endif } void Creature::updateTileCache(const Tile* tile, const Position& pos) { const Position& myPos = getPosition(); if(pos.z == myPos.z) updateTileCache(tile, pos.x - myPos.x, pos.y - myPos.y); } int32_t Creature::getWalkCache(const Position& pos) const { if(!useCacheMap()) return 2; const Position& myPos = getPosition(); if(myPos.z != pos.z) return 0; if(pos == myPos) return 1; int32_t dx = pos.x - myPos.x, dy = pos.y - myPos.y; if((std::abs(dx) <= (mapWalkWidth - 1) / 2) && (std::abs(dy) <= (mapWalkHeight - 1) / 2)) { int32_t x = (mapWalkWidth - 1) / 2 + dx, y = (mapWalkHeight - 1) / 2 + dy; #ifdef __DEBUG__ //testing Tile* tile = g_game.getTile(pos); if(tile && (tile->__queryAdd(0, this, 1, FLAG_PATHFINDING | FLAG_IGNOREFIELDDAMAGE) == RET_NOERROR)) { if(!localMapCache[y][x]) std::cout << "Wrong cache value" << std::endl; } else if(localMapCache[y][x]) std::cout << "Wrong cache value" << std::endl; #endif if(localMapCache[y][x]) return 1; return 0; } //out of range return 2; } void Creature::onAddTileItem(const Tile* tile, const Position& pos, const Item* item) { if(isMapLoaded && pos.z == getPosition().z) updateTileCache(tile, pos); } void Creature::onUpdateTileItem(const Tile* tile, const Position& pos, const Item* oldItem, const ItemType& oldType, const Item* newItem, const ItemType& newType) { if(isMapLoaded && (oldType.blockSolid || oldType.blockPathFind || newType.blockPathFind || newType.blockSolid) && pos.z == getPosition().z) updateTileCache(tile, pos); } void Creature::onRemoveTileItem(const Tile* tile, const Position& pos, const ItemType& iType, const Item* item) { if(isMapLoaded && (iType.blockSolid || iType.blockPathFind || iType.isGroundTile()) && pos.z == getPosition().z) updateTileCache(tile, pos); } void Creature::onCreatureAppear(const Creature* creature) { if(creature == this) { if(useCacheMap()) { isMapLoaded = true; updateMapCache(); } } else if(isMapLoaded && creature->getPosition().z == getPosition().z) updateTileCache(creature->getTile(), creature->getPosition()); } void Creature::onCreatureDisappear(const Creature* creature, bool isLogout) { internalCreatureDisappear(creature, true); if(creature != this && isMapLoaded && creature->getPosition().z == getPosition().z) updateTileCache(creature->getTile(), creature->getPosition()); } void Creature::onRemovedCreature() { setRemoved(); removeList(); if(master && !master->isRemoved()) master->removeSummon(this); } void Creature::onChangeZone(ZoneType_t zone) { if(attackedCreature && zone == ZONE_PROTECTION) internalCreatureDisappear(attackedCreature, false); } void Creature::onAttackedCreatureChangeZone(ZoneType_t zone) { if(zone == ZONE_PROTECTION) internalCreatureDisappear(attackedCreature, false); } void Creature::onCreatureMove(const Creature* creature, const Tile* newTile, const Position& newPos, const Tile* oldTile, const Position& oldPos, bool teleport) { if(creature == this) { lastStep = OTSYS_TIME(); lastStepCost = 1; setLastPosition(oldPos); if(!teleport) { if(oldPos.z != newPos.z || (std::abs(newPos.x - oldPos.x) >= 1 && std::abs(newPos.y - oldPos.y) >= 1)) lastStepCost = 2; } else stopEventWalk(); if(newTile->getZone() != oldTile->getZone()) onChangeZone(getZone()); //update map cache if(isMapLoaded) { if(!teleport && oldPos.z == newPos.z) { Tile* tile = NULL; const Position& myPos = getPosition(); if(oldPos.y > newPos.y) //north { //shift y south for(int32_t y = mapWalkHeight - 1 - 1; y >= 0; --y) memcpy(localMapCache[y + 1], localMapCache[y], sizeof(localMapCache[y])); //update 0 for(int32_t x = -((mapWalkWidth - 1) / 2); x <= ((mapWalkWidth - 1) / 2); ++x) { tile = g_game.getTile(myPos.x + x, myPos.y - ((mapWalkHeight - 1) / 2), myPos.z); updateTileCache(tile, x, -((mapWalkHeight - 1) / 2)); } } else if(oldPos.y < newPos.y) // south { //shift y north for(int32_t y = 0; y <= mapWalkHeight - 1 - 1; ++y) memcpy(localMapCache[y], localMapCache[y + 1], sizeof(localMapCache[y])); //update mapWalkHeight - 1 for(int32_t x = -((mapWalkWidth - 1) / 2); x <= ((mapWalkWidth - 1) / 2); ++x) { tile = g_game.getTile(myPos.x + x, myPos.y + ((mapWalkHeight - 1) / 2), myPos.z); updateTileCache(tile, x, (mapWalkHeight - 1) / 2); } } if(oldPos.x < newPos.x) // east { //shift y west int32_t starty = 0, endy = mapWalkHeight - 1, dy = (oldPos.y - newPos.y); if(dy < 0) endy = endy + dy; else if(dy > 0) starty = starty + dy; for(int32_t y = starty; y <= endy; ++y) { for(int32_t x = 0; x <= mapWalkWidth - 1 - 1; ++x) localMapCache[y][x] = localMapCache[y][x + 1]; } //update mapWalkWidth - 1 for(int32_t y = -((mapWalkHeight - 1) / 2); y <= ((mapWalkHeight - 1) / 2); ++y) { tile = g_game.getTile(myPos.x + ((mapWalkWidth - 1) / 2), myPos.y + y, myPos.z); updateTileCache(tile, (mapWalkWidth - 1) / 2, y); } } else if(oldPos.x > newPos.x) // west { //shift y east int32_t starty = 0, endy = mapWalkHeight - 1, dy = (oldPos.y - newPos.y); if(dy < 0) endy = endy + dy; else if(dy > 0) starty = starty + dy; for(int32_t y = starty; y <= endy; ++y) { for(int32_t x = mapWalkWidth - 1 - 1; x >= 0; --x) localMapCache[y][x + 1] = localMapCache[y][x]; } //update 0 for(int32_t y = -((mapWalkHeight - 1) / 2); y <= ((mapWalkHeight - 1) / 2); ++y) { tile = g_game.getTile(myPos.x - ((mapWalkWidth - 1) / 2), myPos.y + y, myPos.z); updateTileCache(tile, -((mapWalkWidth - 1) / 2), y); } } updateTileCache(oldTile, oldPos); #ifdef __DEBUG__ validateMapCache(); #endif } else updateMapCache(); } } else if(isMapLoaded) { const Position& myPos = getPosition(); if(newPos.z == myPos.z) updateTileCache(newTile, newPos); if(oldPos.z == myPos.z) updateTileCache(oldTile, oldPos); } if(creature == followCreature || (creature == this && followCreature)) { if(hasFollowPath) { isUpdatingPath = true; Dispatcher::getInstance().addTask(createTask( boost::bind(&Game::updateCreatureWalk, &g_game, getID()))); } if(newPos.z != oldPos.z || !canSee(followCreature->getPosition())) internalCreatureDisappear(followCreature, false); } if(creature == attackedCreature || (creature == this && attackedCreature)) { if(newPos.z == oldPos.z && canSee(attackedCreature->getPosition())) { if(hasExtraSwing()) //our target is moving lets see if we can get in hit Dispatcher::getInstance().addTask(createTask( boost::bind(&Game::checkCreatureAttack, &g_game, getID()))); if(newTile->getZone() != oldTile->getZone()) onAttackedCreatureChangeZone(attackedCreature->getZone()); } else internalCreatureDisappear(attackedCreature, false); } } bool Creature::onDeath() { DeathList deathList = getKillers(); bool deny = false; CreatureEventList prepareDeathEvents = getCreatureEvents(CREATURE_EVENT_PREPAREDEATH); for(CreatureEventList::iterator it = prepareDeathEvents.begin(); it != prepareDeathEvents.end(); ++it) { if(!(*it)->executePrepareDeath(this, deathList) && !deny) deny = true; } if(deny) return false; int32_t i = 0, size = deathList.size(), limit = g_config.getNumber(ConfigManager::DEATH_ASSISTS) + 1; if(limit > 0 && size > limit) size = limit; Creature* tmp = NULL; CreatureVector justifyVec; for(DeathList::iterator it = deathList.begin(); it != deathList.end(); ++it, ++i) { if(it->isNameKill()) continue; bool lastHit = it == deathList.begin(); uint32_t flags = KILLFLAG_NONE; if(lastHit) flags |= (uint32_t)KILLFLAG_LASTHIT; if(i < size) { if(it->getKillerCreature()->getPlayer()) tmp = it->getKillerCreature(); else if(it->getKillerCreature()->getPlayerMaster()) tmp = it->getKillerCreature()->getMaster(); } if(tmp) { if(std::find(justifyVec.begin(), justifyVec.end(), tmp) == justifyVec.end()) { flags |= (uint32_t)KILLFLAG_JUSTIFY; justifyVec.push_back(tmp); } tmp = NULL; } if(!it->getKillerCreature()->onKilledCreature(this, flags) && lastHit) return false; if(hasBitSet((uint32_t)KILLFLAG_UNJUSTIFIED, flags)) it->setUnjustified(true); } for(CountMap::iterator it = damageMap.begin(); it != damageMap.end(); ++it) { if((tmp = g_game.getCreatureByID(it->first))) tmp->onAttackedCreatureKilled(this); } dropCorpse(deathList); if(master) master->removeSummon(this); return true; } void Creature::dropCorpse(DeathList deathList) { Item* corpse = createCorpse(deathList); if(corpse) corpse->setParent(VirtualCylinder::virtualCylinder); bool deny = false; CreatureEventList deathEvents = getCreatureEvents(CREATURE_EVENT_DEATH); for(CreatureEventList::iterator it = deathEvents.begin(); it != deathEvents.end(); ++it) { if(!(*it)->executeDeath(this, corpse, deathList) && !deny) deny = true; } if(!corpse) return; corpse->setParent(NULL); if(deny) return; Tile* tile = getTile(); if(!tile) return; Item* splash = NULL; switch(getRace()) { case RACE_VENOM: splash = Item::CreateItem(ITEM_FULLSPLASH, FLUID_GREEN); break; case RACE_BLOOD: splash = Item::CreateItem(ITEM_FULLSPLASH, FLUID_BLOOD); break; default: break; } g_game.internalAddItem(NULL, tile, corpse, INDEX_WHEREEVER, FLAG_NOLIMIT); dropLoot(corpse->getContainer()); g_game.startDecay(corpse); } DeathList Creature::getKillers() { DeathList list; Creature* lhc = NULL; if(!(lhc = g_game.getCreatureByID(lastHitCreature))) list.push_back(DeathEntry(getCombatName(lastDamageSource), 0)); else list.push_back(DeathEntry(lhc, 0)); int32_t requiredTime = g_config.getNumber(ConfigManager::DEATHLIST_REQUIRED_TIME); int64_t now = OTSYS_TIME(); CountBlock_t cb; for(CountMap::const_iterator it = damageMap.begin(); it != damageMap.end(); ++it) { cb = it->second; if((now - cb.ticks) > requiredTime) continue; Creature* mdc = g_game.getCreatureByID(it->first); if(!mdc || mdc == lhc || (lhc && (mdc->getMaster() == lhc || lhc->getMaster() == mdc))) continue; bool deny = false; for(DeathList::iterator fit = list.begin(); fit != list.end(); ++fit) { if(fit->isNameKill()) continue; Creature* tmp = fit->getKillerCreature(); if(!(mdc->getName() == tmp->getName() && mdc->getMaster() == tmp->getMaster()) && (!mdc->getMaster() || (mdc->getMaster() != tmp && mdc->getMaster() != tmp->getMaster())) && (mdc->getSummonCount() <= 0 || tmp->getMaster() != mdc)) continue; deny = true; break; } if(!deny) list.push_back(DeathEntry(mdc, cb.total)); } if(list.size() > 1) std::sort(list.begin() + 1, list.end(), DeathLessThan()); return list; } bool Creature::hasBeenAttacked(uint32_t attackerId) const { CountMap::const_iterator it = damageMap.find(attackerId); if(it != damageMap.end()) return (OTSYS_TIME() - it->second.ticks) <= g_config.getNumber(ConfigManager::PZ_LOCKED); return false; } Item* Creature::createCorpse(DeathList deathList) { return Item::CreateItem(getLookCorpse()); } void Creature::changeHealth(int32_t healthChange) { if(healthChange > 0) health += std::min(healthChange, getMaxHealth() - health); else health = std::max((int32_t)0, health + healthChange); g_game.addCreatureHealth(this); } void Creature::changeMana(int32_t manaChange) { if(manaChange > 0) mana += std::min(manaChange, getMaxMana() - mana); else mana = std::max((int32_t)0, mana + manaChange); } bool Creature::getStorage(const uint32_t key, std::string& value) const { StorageMap::const_iterator it = storageMap.find(key); if(it != storageMap.end()) { value = it->second; return true; } value = "-1"; return false; } bool Creature::setStorage(const uint32_t key, const std::string& value) { storageMap[key] = value; return true; } void Creature::gainHealth(Creature* caster, int32_t healthGain) { if(healthGain > 0) { int32_t prevHealth = getHealth(); changeHealth(healthGain); int32_t effectiveGain = getHealth() - prevHealth; if(caster) caster->onTargetCreatureGainHealth(this, effectiveGain); } else changeHealth(healthGain); } void Creature::drainHealth(Creature* attacker, CombatType_t combatType, int32_t damage) { lastDamageSource = combatType; onAttacked(); changeHealth(-damage); if(attacker) attacker->onAttackedCreatureDrainHealth(this, damage); } bool Creature::isGhostPokemon() const{ bool ret = false; return ret; } void Creature::drainMana(Creature* attacker, CombatType_t combatType, int32_t damage) { lastDamageSource = combatType; onAttacked(); changeMana(-damage); if(attacker) attacker->onAttackedCreatureDrainMana(this, damage); } BlockType_t Creature::blockHit(Creature* attacker, CombatType_t combatType, int32_t& damage, bool checkDefense/* = false*/, bool checkArmor/* = false*/) { BlockType_t blockType = BLOCK_NONE; if(isImmune(combatType)) { damage = 0; blockType = BLOCK_IMMUNITY; } else if(checkDefense || checkArmor) { bool hasDefense = false; if(blockCount > 0) { --blockCount; hasDefense = true; } if(checkDefense && hasDefense) { int32_t maxDefense = getDefense(), minDefense = maxDefense / 2; damage -= random_range(minDefense, maxDefense); if(damage <= 0) { damage = 0; blockType = BLOCK_DEFENSE; checkArmor = false; } } if(checkArmor) { int32_t armorValue = getArmor(), minArmorReduction = 0, maxArmorReduction = 0; if(armorValue > 1) { minArmorReduction = (int32_t)std::ceil(armorValue * 0.475); maxArmorReduction = (int32_t)std::ceil( ((armorValue * 0.475) - 1) + minArmorReduction); } else if(armorValue == 1) { minArmorReduction = 1; maxArmorReduction = 1; } damage -= random_range(minArmorReduction, maxArmorReduction); if(damage <= 0) { damage = 0; blockType = BLOCK_ARMOR; } } if(hasDefense && blockType != BLOCK_NONE) onBlockHit(blockType); } if(attacker) { attacker->onAttackedCreature(this); attacker->onAttackedCreatureBlockHit(this, blockType); } onAttacked(); return blockType; } bool Creature::setAttackedCreature(Creature* creature) { if(creature) { const Position& creaturePos = creature->getPosition(); if(creaturePos.z != getPosition().z || !canSee(creaturePos)) { attackedCreature = NULL; return false; } } attackedCreature = creature; if(attackedCreature) { onAttackedCreature(attackedCreature); attackedCreature->onAttacked(); } for(std::list<Creature*>::iterator cit = summons.begin(); cit != summons.end(); ++cit) (*cit)->setAttackedCreature(creature); return true; } void Creature::getPathSearchParams(const Creature* creature, FindPathParams& fpp) const { fpp.fullPathSearch = !hasFollowPath; fpp.clearSight = false; fpp.maxSearchDist = 12; fpp.minTargetDist = fpp.maxTargetDist = 1; } void Creature::getPathToFollowCreature() { if(followCreature) { FindPathParams fpp; getPathSearchParams(followCreature, fpp); if(g_game.getPathToEx(this, followCreature->getPosition(), listWalkDir, fpp)) { hasFollowPath = true; startAutoWalk(listWalkDir); } else hasFollowPath = false; } onFollowCreatureComplete(followCreature); } bool Creature::setFollowCreature(Creature* creature, bool fullPathSearch /*= false*/) { if(creature) { if(followCreature == creature) return true; const Position& creaturePos = creature->getPosition(); if(creaturePos.z != getPosition().z || !canSee(creaturePos)) { followCreature = NULL; return false; } if(!listWalkDir.empty()) { listWalkDir.clear(); onWalkAborted(); } hasFollowPath = forceUpdateFollowPath = false; followCreature = creature; isUpdatingPath = true; } else { isUpdatingPath = false; followCreature = NULL; } onFollowCreature(creature); return true; } double Creature::getDamageRatio(Creature* attacker) const { double totalDamage = 0, attackerDamage = 0; for(CountMap::const_iterator it = damageMap.begin(); it != damageMap.end(); ++it) { totalDamage += it->second.total; if(it->first == attacker->getID()) attackerDamage += it->second.total; } return attackerDamage / totalDamage; } void Creature::addDamagePoints(Creature* attacker, int32_t damagePoints) { uint32_t attackerId = 0; if(attacker) attackerId = attacker->getID(); CountMap::iterator it = damageMap.find(attackerId); if(it != damageMap.end()) { it->second.ticks = OTSYS_TIME(); if(damagePoints > 0) it->second.total += damagePoints; } else damageMap[attackerId] = CountBlock_t(damagePoints); if(damagePoints > 0) lastHitCreature = attackerId; } void Creature::addHealPoints(Creature* caster, int32_t healthPoints) { if(healthPoints <= 0) return; uint32_t casterId = 0; if(caster) casterId = caster->getID(); CountMap::iterator it = healMap.find(casterId); if(it != healMap.end()) { it->second.ticks = OTSYS_TIME(); it->second.total += healthPoints; } else healMap[casterId] = CountBlock_t(healthPoints); } void Creature::onAddCondition(ConditionType_t type, bool hadCondition) { if(type == CONDITION_INVISIBLE) { if(!hadCondition) g_game.internalCreatureChangeVisible(this, VISIBLE_DISAPPEAR); } else if(type == CONDITION_PARALYZE) { if(hasCondition(CONDITION_HASTE)) removeCondition(CONDITION_HASTE); } else if(type == CONDITION_HASTE) { if(hasCondition(CONDITION_PARALYZE)) removeCondition(CONDITION_PARALYZE); } } void Creature::onEndCondition(ConditionType_t type) { if(type == CONDITION_INVISIBLE && !hasCondition(CONDITION_INVISIBLE, -1, false)) g_game.internalCreatureChangeVisible(this, VISIBLE_APPEAR); } void Creature::onTickCondition(ConditionType_t type, int32_t interval, bool& _remove) { if(const MagicField* field = getTile()->getFieldItem()) { switch(type) { case CONDITION_FIRE: _remove = field->getCombatType() != COMBAT_FIREDAMAGE; break; case CONDITION_ENERGY: _remove = field->getCombatType() != COMBAT_ENERGYDAMAGE; break; case CONDITION_POISON: _remove = field->getCombatType() != COMBAT_EARTHDAMAGE; break; case CONDITION_DROWN: _remove = field->getCombatType() != COMBAT_DROWNDAMAGE; break; default: break; } } } void Creature::onCombatRemoveCondition(const Creature* attacker, Condition* condition) { removeCondition(condition); } void Creature::onIdleStatus() { if(getHealth() > 0) { healMap.clear(); damageMap.clear(); } } void Creature::onAttackedCreatureDrainHealth(Creature* target, int32_t points) { onAttackedCreatureDrain(target, points); } void Creature::onAttackedCreatureDrainMana(Creature* target, int32_t points) { onAttackedCreatureDrain(target, points); } void Creature::onAttackedCreatureDrain(Creature* target, int32_t points) { target->addDamagePoints(this, points); } void Creature::onTargetCreatureGainHealth(Creature* target, int32_t points) { target->addHealPoints(this, points); } void Creature::onAttackedCreatureKilled(Creature* target) { if(target == this) return; double gainExp = target->getGainedExperience(this); onGainExperience(gainExp, !target->getPlayer(), false); } Creature* Creature::pushBackSummonOne(){ // aqui Creature* a = NULL; if(!summons.empty()) { std::list<Creature*>::iterator cit; std::list<Creature*> despawnList; for(cit = summons.begin(); cit != summons.end(); ++cit) { a = (*cit); break; } } return a; } bool Creature::onKilledCreature(Creature* target, uint32_t& flags) { bool ret = true; if(master) ret = master->onKilledCreature(target, flags); CreatureEventList killEvents = getCreatureEvents(CREATURE_EVENT_KILL); if(!hasBitSet((uint32_t)KILLFLAG_LASTHIT, flags)) { for(CreatureEventList::iterator it = killEvents.begin(); it != killEvents.end(); ++it) (*it)->executeKill(this, target, false); return true; } for(CreatureEventList::iterator it = killEvents.begin(); it != killEvents.end(); ++it) { if(!(*it)->executeKill(this, target, true) && ret) ret = false; } return ret; } void Creature::onGainExperience(double& gainExp, bool fromMonster, bool multiplied) { if(gainExp <= 0) return; if(master) { gainExp = gainExp / 2; master->onGainExperience(gainExp, fromMonster, multiplied); } else if(!multiplied) gainExp *= g_config.getDouble(ConfigManager::RATE_EXPERIENCE); int16_t color = g_config.getNumber(ConfigManager::EXPERIENCE_COLOR); if(color < 0) color = random_range(0, 255); std::stringstream ss; ss << (uint64_t)gainExp; g_game.addAnimatedText(getPosition(), (uint8_t)color, ss.str()); } void Creature::onGainSharedExperience(double& gainExp, bool fromMonster, bool multiplied) { if(gainExp <= 0) return; if(master) { gainExp = gainExp / 2; master->onGainSharedExperience(gainExp, fromMonster, multiplied); } else if(!multiplied) gainExp *= g_config.getDouble(ConfigManager::RATE_EXPERIENCE); int16_t color = g_config.getNumber(ConfigManager::EXPERIENCE_COLOR); if(color < 0) color = random_range(0, 255); std::stringstream ss; ss << (uint64_t)gainExp; g_game.addAnimatedText(getPosition(), (uint8_t)color, ss.str()); } void Creature::addSummon(Creature* creature) { creature->setDropLoot(LOOT_DROP_NONE); creature->setLossSkill(false); creature->setMaster(this); creature->addRef(); summons.push_back(creature); } void Creature::removeSummon(const Creature* creature) { std::list<Creature*>::iterator it = std::find(summons.begin(), summons.end(), creature); if(it == summons.end()) return; (*it)->setMaster(NULL); (*it)->unRef(); summons.erase(it); } void Creature::destroySummons() { for(std::list<Creature*>::iterator it = summons.begin(); it != summons.end(); ++it) { (*it)->setAttackedCreature(NULL); (*it)->changeHealth(-(*it)->getHealth()); (*it)->setMaster(NULL); (*it)->unRef(); } summons.clear(); } bool Creature::addCondition(Condition* condition) { if(!condition) return false; bool hadCondition = hasCondition(condition->getType(), -1, false); if(Condition* previous = getCondition(condition->getType(), condition->getId(), condition->getSubId())) { previous->addCondition(this, condition); delete condition; return true; } if(condition->startCondition(this)) { conditions.push_back(condition); onAddCondition(condition->getType(), hadCondition); return true; } delete condition; return false; } bool Creature::addCombatCondition(Condition* condition) { bool hadCondition = hasCondition(condition->getType(), -1, false); //Caution: condition variable could be deleted after the call to addCondition ConditionType_t type = condition->getType(); if(!addCondition(condition)) return false; onAddCombatCondition(type, hadCondition); return true; } void Creature::removeCondition(ConditionType_t type) { for(ConditionList::iterator it = conditions.begin(); it != conditions.end();) { if((*it)->getType() != type) { ++it; continue; } Condition* condition = *it; it = conditions.erase(it); condition->endCondition(this, CONDITIONEND_ABORT); onEndCondition(condition->getType()); delete condition; } } void Creature::removeCondition(ConditionType_t type, ConditionId_t id) { for(ConditionList::iterator it = conditions.begin(); it != conditions.end();) { if((*it)->getType() != type || (*it)->getId() != id) { ++it; continue; } Condition* condition = *it; it = conditions.erase(it); condition->endCondition(this, CONDITIONEND_ABORT); onEndCondition(condition->getType()); delete condition; } } void Creature::removeCondition(Condition* condition) { ConditionList::iterator it = std::find(conditions.begin(), conditions.end(), condition); if(it != conditions.end()) { Condition* condition = *it; it = conditions.erase(it); condition->endCondition(this, CONDITIONEND_ABORT); onEndCondition(condition->getType()); delete condition; } } void Creature::removeCondition(const Creature* attacker, ConditionType_t type) { ConditionList tmpList = conditions; for(ConditionList::iterator it = tmpList.begin(); it != tmpList.end(); ++it) { if((*it)->getType() == type) onCombatRemoveCondition(attacker, *it); } } void Creature::removeConditions(ConditionEnd_t reason, bool onlyPersistent/* = true*/) { for(ConditionList::iterator it = conditions.begin(); it != conditions.end();) { if(onlyPersistent && !(*it)->isPersistent()) { ++it; continue; } Condition* condition = *it; it = conditions.erase(it); condition->endCondition(this, reason); onEndCondition(condition->getType()); delete condition; } } Condition* Creature::getCondition(ConditionType_t type, ConditionId_t id, uint32_t subId/* = 0*/) const { for(ConditionList::const_iterator it = conditions.begin(); it != conditions.end(); ++it) { if((*it)->getType() == type && (*it)->getId() == id && (*it)->getSubId() == subId) return *it; } return NULL; } void Creature::executeConditions(uint32_t interval) { for(ConditionList::iterator it = conditions.begin(); it != conditions.end();) { if((*it)->executeCondition(this, interval)) { ++it; continue; } Condition* condition = *it; it = conditions.erase(it); condition->endCondition(this, CONDITIONEND_TICKS); onEndCondition(condition->getType()); delete condition; } } bool Creature::hasCondition(ConditionType_t type, int32_t subId/* = 0*/, bool checkTime/* = true*/) const { if(isSuppress(type)) return false; for(ConditionList::const_iterator it = conditions.begin(); it != conditions.end(); ++it) { if((*it)->getType() != type || (subId != -1 && (*it)->getSubId() != (uint32_t)subId)) continue; if(!checkTime || g_config.getBool(ConfigManager::OLD_CONDITION_ACCURACY) || !(*it)->getEndTime() || (*it)->getEndTime() >= OTSYS_TIME()) return true; } return false; } bool Creature::isImmune(CombatType_t type) const { return ((getDamageImmunities() & (uint32_t)type) == (uint32_t)type); } bool Creature::isImmune(ConditionType_t type) const { return ((getConditionImmunities() & (uint32_t)type) == (uint32_t)type); } bool Creature::isSuppress(ConditionType_t type) const { return ((getConditionSuppressions() & (uint32_t)type) == (uint32_t)type); } std::string Creature::getDescription(int32_t lookDistance) const { return "a creature"; } int32_t Creature::getStepDuration(Direction dir) const { if(dir == NORTHWEST || dir == NORTHEAST || dir == SOUTHWEST || dir == SOUTHEAST) return getStepDuration() * 2; return getStepDuration(); } int32_t Creature::getStepDuration() const { if(removed) return 0; uint32_t stepSpeed = getStepSpeed(); if(!stepSpeed) return 0; const Tile* tile = getTile(); if(!tile || !tile->ground) return 0; return ((1000 * Item::items[tile->ground->getID()].speed) / stepSpeed) * lastStepCost; } int64_t Creature::getEventStepTicks() const { int64_t ret = getWalkDelay(); if(ret > 0) return ret; return getStepDuration(); } void Creature::getCreatureLight(LightInfo& light) const { light = internalLight; } void Creature::setNormalCreatureLight() { internalLight.level = internalLight.color = 0; } bool Creature::registerCreatureEvent(const std::string& name) { CreatureEvent* event = g_creatureEvents->getEventByName(name); if(!event) //check for existance return false; for(CreatureEventList::iterator it = eventsList.begin(); it != eventsList.end(); ++it) { if((*it) == event) //do not allow registration of same event more than once return false; } if(!hasEventRegistered(event->getEventType())) //there's no such type registered yet, so set the bit in the bitfield scriptEventsBitField |= ((uint32_t)1 << event->getEventType()); eventsList.push_back(event); return true; } CreatureEventList Creature::getCreatureEvents(CreatureEventType_t type) { CreatureEventList retList; if(!hasEventRegistered(type)) return retList; for(CreatureEventList::iterator it = eventsList.begin(); it != eventsList.end(); ++it) { if((*it)->getEventType() == type) retList.push_back(*it); } return retList; } FrozenPathingConditionCall::FrozenPathingConditionCall(const Position& _targetPos) { targetPos = _targetPos; } bool FrozenPathingConditionCall::isInRange(const Position& startPos, const Position& testPos, const FindPathParams& fpp) const { int32_t dxMin = ((fpp.fullPathSearch || (startPos.x - targetPos.x) <= 0) ? fpp.maxTargetDist : 0), dxMax = ((fpp.fullPathSearch || (startPos.x - targetPos.x) >= 0) ? fpp.maxTargetDist : 0), dyMin = ((fpp.fullPathSearch || (startPos.y - targetPos.y) <= 0) ? fpp.maxTargetDist : 0), dyMax = ((fpp.fullPathSearch || (startPos.y - targetPos.y) >= 0) ? fpp.maxTargetDist : 0); if(testPos.x > targetPos.x + dxMax || testPos.x < targetPos.x - dxMin) return false; if(testPos.y > targetPos.y + dyMax || testPos.y < targetPos.y - dyMin) return false; return true; } bool FrozenPathingConditionCall::operator()(const Position& startPos, const Position& testPos, const FindPathParams& fpp, int32_t& bestMatchDist) const { if(!isInRange(startPos, testPos, fpp)) return false; if(fpp.clearSight && !g_game.isSightClear(testPos, targetPos, true)) return false; int32_t testDist = std::max(std::abs(targetPos.x - testPos.x), std::abs(targetPos.y - testPos.y)); if(fpp.maxTargetDist == 1) return (testDist >= fpp.minTargetDist && testDist <= fpp.maxTargetDist); if(testDist <= fpp.maxTargetDist) { if(testDist < fpp.minTargetDist) return false; if(testDist == fpp.maxTargetDist) { bestMatchDist = 0; return true; } else if(testDist > bestMatchDist) { //not quite what we want, but the best so far bestMatchDist = testDist; return true; } } return false; } Link para o comentário Compartilhar em outros sites More sharing options...
Visitante Postado Julho 2, 2018 Share Postado Julho 2, 2018 3 horas atrás, Josegvb disse: teria como me ajudar? nas minhas sources nao achei o if(m_showStaticSquare && animate) { nem g_painter->drawBoundingRect(Rect(dest + (animationOffset - getDisplacement() + 2)*scaleFactor, Size(28, 28)*scaleFactor), std::max<int>((int)(2*scaleFactor), 1)); teria como olhar no arquivo? creature.cpp É na source do client Josegvb reagiu a isso 1 Link para o comentário Compartilhar em outros sites More sharing options...
Developer Berg 65 Postado Julho 2, 2018 Share Postado Julho 2, 2018 ceetros, esse código tem alguma mudança daquela sua outra postagem ? Link para o comentário Compartilhar em outros sites More sharing options...
Visitante Postado Julho 2, 2018 Share Postado Julho 2, 2018 40 minutos atrás, ricardoberg disse: ceetros, esse código tem alguma mudança daquela sua outra postagem ? Na verdade, não. Esse só tem a imagem a mais. Link para o comentário Compartilhar em outros sites More sharing options...
Visitante Postado Julho 3, 2018 Share Postado Julho 3, 2018 22 horas atrás, Walox disse: Sera que inves dele usar uma imagem teria como por para puxar um Effects ? pois daria mais liberdade para fazer targets animados e talz tentei usar a função do APNG mas parece que não aceitou Tem, só fazer. E a parte do apng, a função que eu usei só funciona em imagem estática. Link para o comentário Compartilhar em outros sites More sharing options...
boxxer321 67 Postado Julho 11, 2018 Share Postado Julho 11, 2018 não achei essa linha no meu creature.cpp g_painter->drawBoundingRect(Rect(dest + (animationOffset - getDisplacement() + 2)*scaleFactor, Size(28, 28)*scaleFactor), std::max<int>((int)(2*scaleFactor), 1)); se puder dar uma olhada: Spoiler /* * Copyright (c) 2010-2017 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/stdext/format.h> #include <framework/graphics/graphics.h> #include <framework/core/eventdispatcher.h> #include <framework/core/clock.h> #include <framework/graphics/paintershaderprogram.h> #include <framework/graphics/ogl/painterogl2_shadersources.h> #include <framework/graphics/texturemanager.h> #include <framework/graphics/framebuffermanager.h> #include <framework/graphics/image.h> #include "spritemanager.h" #include <framework/core/resourcemanager.h> #include <framework/core/filestream.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_icon = Otc::NpcIconNone; 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); m_outfitColor = Color::white; } 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) { EffectPtr effect = EffectPtr(new Effect()); effect->setId(819); g_painter->setColor(m_timedSquareColor); Rect rect = Rect(dest + (animationOffset - getDisplacement())*scaleFactor, Size(Otc::TILE_PIXELS, Otc::TILE_PIXELS)*scaleFactor); g_painter->drawTexturedRect(rect, effect->getThingType()->getTextureEX(0)); g_painter->setColor(Color::white); g_painter->setColor(Color::white); } if(m_showStaticSquare && animate) { EffectPtr effect = EffectPtr(new Effect()); effect->setId(819); g_painter->setColor(m_staticSquareColor); Rect rect = Rect(dest + (animationOffset - getDisplacement())*scaleFactor, Size(Otc::TILE_PIXELS, Otc::TILE_PIXELS)*scaleFactor); g_painter->drawTexturedRect(rect, effect->getThingType()->getTextureEX(0)); 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, 3); if(light.color == 0 || light.color > 215) light.color = 215; } if(light.intensity > 0) lightView->addLightSource(dest + (animationOffset + Point(16,16)) * scaleFactor, scaleFactor, light); } } int countTest = 0; void Creature::internalDrawOutfit(Point dest, float scaleFactor, bool animateWalk, bool animateIdle, Otc::Direction direction, LightView *lightView) { g_painter->setColor(m_outfitColor); // 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; PointF jumpOffset = m_jumpOffset * scaleFactor; dest -= Point(stdext::round(jumpOffset.x), stdext::round(jumpOffset.y)); // 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 = getThingType(); if(m_skull >= 1){ float initEffe = 0.4f, endEffe = 0.6f; int exactSize = getExactSize(); double scaleMult = 1.12, axsX = 0.97, axsY = 1.2; // ate 42 de exactSize Color azul = Color(0.0f, 128.0, 255.0, 1.0f), verde = Color(51, 255, 51), laranja = Color(255, 102, 0), azulCya = Color(51, 204, 255), white = Color::white, viliota = Color(102, 0, 255), roxa = Color(153, 0, 204), redScarlat = Color(230, 0, 0), amarelo = Color(255, 255, 0), preto = Color::black, rosa = Color(255, 51, 153), jeaneSoisQuoi = Color(0, 102, 102), cou = Color(204, 51, 0); Color auraColor = azul;// azul //Color config 1 = black, 2 = blue, 3 = green, 4 = pink, 5 = orange if(m_skull == 2) auraColor = verde; else if(m_skull == 3) auraColor = laranja; else if (m_skull == 4) auraColor = azulCya; else if (m_skull == 5) auraColor = white; else if (m_skull == 6) auraColor = viliota; else if (m_skull == 7) auraColor = roxa; else if (m_skull == ? auraColor = redScarlat; else if (m_skull == 9) auraColor = amarelo; else if (m_skull == 10) { initEffe = 0.7f; endEffe = 0.9f; auraColor = preto; } else if (m_skull == 11) { auraColor = rosa; initEffe = 0.3f; endEffe = 0.7f; } else if (m_skull == 12) auraColor = jeaneSoisQuoi; else if (m_skull == 13) auraColor = cou; if(exactSize == 52) { // tamanho das sprites axsY = 0.92; }else if(exactSize == 32) { // tamanho das sprites scaleMult = 1.16; axsX = 0.94; axsY = 0.92; } Point p = Point(dest.x-axsX, dest.y-axsY); //Rect rect = Rect(p.x, p.y, datType->getTexture(animationPhase)->getSize()); countTest++; //colored raibow aura if (m_skull == 14) { if (countTest <= 40) auraColor = white; else if (countTest >= 41 && countTest <= 80) auraColor = redScarlat; else if (countTest >= 81 && countTest <= 120) auraColor = verde; else if (countTest >= 121 && countTest <= 160) auraColor = laranja; else if (countTest >= 161 && countTest <= 200) auraColor = azul; else if (countTest >= 201 && countTest <= 240) auraColor = amarelo; else if (countTest >= 241) countTest = 0; }else { if (countTest <= 60) { g_painter->setOpacity(initEffe); } else if (countTest >= 61 && countTest <= 110) { g_painter->setOpacity(endEffe); } else if (countTest >= 111) countTest = 0; } g_painter->setColor(auraColor); datType->drawEX(p, scaleFactor*scaleMult, 0, xPattern, yPattern, zPattern, animationPhase, yPattern == 0 ? lightView : nullptr); //g_painter->drawTexturedRect(rect, datType->getTexture(animationPhase, true)); g_painter->setOpacity(1.0f); } // if(m_skull >= 1 && m_skullTexture){ // g_painter->setOpacity(0.7f); //} g_painter->setColor(m_outfitColor); 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<int>(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<int>(animationPhase+1, animationPhases); type->draw(dest - (getDisplacement() * scaleFactor), scaleFactor, 0, 0, 0, 0, animationPhase, lightView); } g_painter->resetColor(); g_painter->setOpacity(1.0f); } 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(); int frameSize; if(!resize) frameSize = std::max<int>(exactSize * 0.75f, 2 * Otc::TILE_PIXELS * 0.75f); else if(!(frameSize = exactSize)) return; if(g_graphics.canUseFBO()) { const FrameBufferPtr& outfitBuffer = g_framebuffers.getTemporaryFrameBuffer(); outfitBuffer->resize(Size(frameSize, frameSize)); outfitBuffer->bind(); g_painter->setAlphaWriting(true); g_painter->clear(Color::alpha); internalDrawOutfit(Point(frameSize - Otc::TILE_PIXELS, frameSize - Otc::TILE_PIXELS) + getDisplacement(), 1, false, true, Otc::South); outfitBuffer->release(); outfitBuffer->draw(destRect, Rect(0,0,frameSize,frameSize)); } else { float scaleFactor = destRect.width() / (float)frameSize; 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, int drawFlags) { if(m_healthPercent < 1 || m_outfit.getId() == 84) // creature is dead return; Color fillColor = Color(96, 96, 96); if(!useGray) fillColor = m_informationColor; int exactSize = getExactSize(); int d = 0, dx = 0; if(exactSize <= 34) d = 5; else if(exactSize >= 35 && exactSize <= 48) d = 15; else if(exactSize >= 49 && exactSize <= 52) d = 25; else if(exactSize >= 53 && exactSize <= 57) d = 30; else if(exactSize >= 58 && exactSize <= 69) d = 25; else if(exactSize == 74) d = 37; dx = d /2; if(exactSize <= 34) dx = 17; // calculate main rects Rect backgroundRect = Rect(point.x - dx, point.y - d, 40, 6); backgroundRect.bind(parentRect); Size nameSize = m_nameCache.getTextSize(); Rect textRect = Rect(point.x - nameSize.width() / 2, point.y-14, 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(); int calc = ((m_healthPercent / 100.0) * 40.0) + 60; std::string nameBar = std::to_string(calc); if (calc == 100) nameBar = "full"; // draw if(g_game.getFeature(Otc::GameBlueNpcNameColor) && isNpc() && m_healthPercent == 100 && !useGray) fillColor = Color(0x66, 0xcc, 0xff); if(drawFlags & Otc::DrawBars && (!isNpc() || !g_game.getFeature(Otc::GameHideNpcNames))) { g_painter->setColor(Color::white); ImagePtr backgroundLifeBar = Image::load("data/images/game/lifebar/background"); TexturePtr bgLifeBar = TexturePtr(new Texture(backgroundLifeBar, false)); //g_painter->drawFilledRect(backgroundRect); g_painter->drawTexturedRect(backgroundRect, bgLifeBar); ImagePtr healthLifeBar = Image::load("data/images/game/lifebar/" + nameBar); TexturePtr lifeBar = TexturePtr(new Texture(healthLifeBar, false)); g_painter->drawTexturedRect(healthRect, lifeBar); //g_painter->drawFilledRect(healthRect); } if(drawFlags & Otc::DrawNames) { g_painter->setColor(Color(213, 213, 0)); //m_nameCache.setText(std::to_string(m_outfit.getId())); //m_nameCache.set m_nameCache.draw(textRect); } if (m_skull >= 50 && m_skull <= 56) { // 0 = on | 1 = use | 2 = off // 50 | 49 | 48 //0 0 0 0 0 0 | 0 0 0 0 0 1 | 0 0 0 0 1 2 // g_painter->setColor(Color::white); ImagePtr imgBallON = Image::load("data/images/game/duel/pokeball_on"); ImagePtr imgBallOFF = Image::load("data/images/game/duel/pokeball_off"); ImagePtr imgBallUSE = Image::load("data/images/game/duel/pokeball_use"); int duel_mode = m_skull - 50, ball_counts = m_emblem - 50; TexturePtr ballTexture1 = TexturePtr(new Texture(imgBallON, false)); TexturePtr ballTexture2 = TexturePtr(new Texture(imgBallON, false)); TexturePtr ballTexture3 = TexturePtr(new Texture(imgBallON, false)); TexturePtr ballTexture4 = TexturePtr(new Texture(imgBallON, false)); TexturePtr ballTexture5 = TexturePtr(new Texture(imgBallON, false)); TexturePtr ballTexture6 = TexturePtr(new Texture(imgBallON, false)); if (duel_mode == 1) { int countPos = 23 - (10 * 3); if (ball_counts == 1) ballTexture1 = TexturePtr(new Texture(imgBallUSE, false)); ballTexture1->setSmooth(true); Rect skullRect = Rect(backgroundRect.x() - countPos, backgroundRect.y() - 25, ballTexture1->getSize()); g_painter->setOpacity(0.8f); g_painter->drawTexturedRect(skullRect, ballTexture1); } else if (duel_mode == 2) { int countPos = 8 - 10; int countPos2 = 8 - 20; if (ball_counts == 4) { ballTexture2 = TexturePtr(new Texture(imgBallUSE, false)); } else if (ball_counts == 3) { ballTexture2 = TexturePtr(new Texture(imgBallOFF, false)); } else if (ball_counts == 2) { ballTexture2 = TexturePtr(new Texture(imgBallOFF, false)); ballTexture1 = TexturePtr(new Texture(imgBallUSE, false)); } else if (ball_counts == 1) { ballTexture2 = TexturePtr(new Texture(imgBallOFF, false)); ballTexture1 = TexturePtr(new Texture(imgBallOFF, false)); } Rect skullRect = Rect(backgroundRect.x() - countPos, backgroundRect.y() - 25, ballTexture1->getSize()); Rect skullRect2 = Rect(backgroundRect.x() - countPos2, backgroundRect.y() - 25, ballTexture1->getSize()); g_painter->setOpacity(0.8f); g_painter->drawTexturedRect(skullRect, ballTexture1); g_painter->drawTexturedRect(skullRect2, ballTexture2); } else if (duel_mode == 3) { int countPos = 13 - 10; int countPos2 = 13 - 20; int countPos3 = 13 - 30; if (ball_counts == 6) { ballTexture3 = TexturePtr(new Texture(imgBallUSE, false)); } else if (ball_counts == 5) { ballTexture3 = TexturePtr(new Texture(imgBallOFF, false)); } else if (ball_counts == 4) { ballTexture3 = TexturePtr(new Texture(imgBallOFF, false)); ballTexture2 = TexturePtr(new Texture(imgBallUSE, false)); } else if (ball_counts == 3) { ballTexture3 = TexturePtr(new Texture(imgBallOFF, false)); ballTexture2 = TexturePtr(new Texture(imgBallOFF, false)); } else if (ball_counts == 2) { ballTexture3 = TexturePtr(new Texture(imgBallOFF, false)); ballTexture2 = TexturePtr(new Texture(imgBallOFF, false)); ballTexture1 = TexturePtr(new Texture(imgBallUSE, false)); } else if (ball_counts == 1) { ballTexture3 = TexturePtr(new Texture(imgBallOFF, false)); ballTexture2 = TexturePtr(new Texture(imgBallOFF, false)); ballTexture1 = TexturePtr(new Texture(imgBallOFF, false)); } Rect skullRect = Rect(backgroundRect.x() - countPos, backgroundRect.y() - 25, ballTexture1->getSize()); Rect skullRect2 = Rect(backgroundRect.x() - countPos2, backgroundRect.y() - 25, ballTexture1->getSize()); Rect skullRect3 = Rect(backgroundRect.x() - countPos3, backgroundRect.y() - 25, ballTexture1->getSize()); g_painter->setOpacity(0.8f); g_painter->drawTexturedRect(skullRect, ballTexture1); g_painter->drawTexturedRect(skullRect2, ballTexture2); g_painter->drawTexturedRect(skullRect3, ballTexture3); } else if (duel_mode == 4) { int countPos = 15 - 10; int countPos2 = 15 - 20; int countPos3 = 15 - 30; int countPos4 = 15 - 40; if (ball_counts == ? { ballTexture4 = TexturePtr(new Texture(imgBallUSE, false)); } else if (ball_counts == 7) { ballTexture4 = TexturePtr(new Texture(imgBallOFF, false)); } else if (ball_counts == 6) { ballTexture4 = TexturePtr(new Texture(imgBallOFF, false)); ballTexture3 = TexturePtr(new Texture(imgBallUSE, false)); } else if (ball_counts == 5) { ballTexture4 = TexturePtr(new Texture(imgBallOFF, false)); ballTexture3 = TexturePtr(new Texture(imgBallOFF, false)); } else if (ball_counts == 4) { ballTexture4 = TexturePtr(new Texture(imgBallOFF, false)); ballTexture3 = TexturePtr(new Texture(imgBallOFF, false)); ballTexture2 = TexturePtr(new Texture(imgBallUSE, false)); } else if (ball_counts == 3) { ballTexture4 = TexturePtr(new Texture(imgBallOFF, false)); ballTexture3 = TexturePtr(new Texture(imgBallOFF, false)); ballTexture2 = TexturePtr(new Texture(imgBallOFF, false)); } else if (ball_counts == 2) { ballTexture4 = TexturePtr(new Texture(imgBallOFF, false)); ballTexture3 = TexturePtr(new Texture(imgBallOFF, false)); ballTexture2 = TexturePtr(new Texture(imgBallOFF, false)); ballTexture1 = TexturePtr(new Texture(imgBallUSE, false)); } else if (ball_counts == 1) { ballTexture4 = TexturePtr(new Texture(imgBallOFF, false)); ballTexture3 = TexturePtr(new Texture(imgBallOFF, false)); ballTexture2 = TexturePtr(new Texture(imgBallOFF, false)); ballTexture1 = TexturePtr(new Texture(imgBallOFF, false)); } Rect skullRect = Rect(backgroundRect.x() - countPos, backgroundRect.y() - 25, ballTexture1->getSize()); Rect skullRect2 = Rect(backgroundRect.x() - countPos2, backgroundRect.y() - 25, ballTexture1->getSize()); Rect skullRect3 = Rect(backgroundRect.x() - countPos3, backgroundRect.y() - 25, ballTexture1->getSize()); Rect skullRect4 = Rect(backgroundRect.x() - countPos4, backgroundRect.y() - 25, ballTexture1->getSize()); g_painter->setOpacity(0.8f); g_painter->drawTexturedRect(skullRect, ballTexture1); g_painter->drawTexturedRect(skullRect2, ballTexture2); g_painter->drawTexturedRect(skullRect3, ballTexture3); g_painter->drawTexturedRect(skullRect4, ballTexture4); } else if (duel_mode == 5) { int countPos = 18 - 10; int countPos2 = 18 - 20; int countPos3 = 18 - 30; int countPos4 = 18 - 40; int countPos5 = 18 - 50; if (ball_counts == 10) { ballTexture5 = TexturePtr(new Texture(imgBallUSE, false)); } else if (ball_counts == 9) { ballTexture5 = TexturePtr(new Texture(imgBallOFF, false)); } else if (ball_counts == ? { ballTexture5 = TexturePtr(new Texture(imgBallOFF, false)); ballTexture4 = TexturePtr(new Texture(imgBallUSE, false)); } else if (ball_counts == 7) { ballTexture5 = TexturePtr(new Texture(imgBallOFF, false)); ballTexture4 = TexturePtr(new Texture(imgBallOFF, false)); } else if (ball_counts == 6) { ballTexture5 = TexturePtr(new Texture(imgBallOFF, false)); ballTexture4 = TexturePtr(new Texture(imgBallOFF, false)); ballTexture3 = TexturePtr(new Texture(imgBallUSE, false)); } else if (ball_counts == 5) { ballTexture5 = TexturePtr(new Texture(imgBallOFF, false)); ballTexture4 = TexturePtr(new Texture(imgBallOFF, false)); ballTexture3 = TexturePtr(new Texture(imgBallOFF, false)); } else if (ball_counts == 4) { ballTexture5 = TexturePtr(new Texture(imgBallOFF, false)); ballTexture4 = TexturePtr(new Texture(imgBallOFF, false)); ballTexture3 = TexturePtr(new Texture(imgBallOFF, false)); ballTexture2 = TexturePtr(new Texture(imgBallUSE, false)); } else if (ball_counts == 3) { ballTexture5 = TexturePtr(new Texture(imgBallOFF, false)); ballTexture4 = TexturePtr(new Texture(imgBallOFF, false)); ballTexture3 = TexturePtr(new Texture(imgBallOFF, false)); ballTexture2 = TexturePtr(new Texture(imgBallOFF, false)); } else if (ball_counts == 2) { ballTexture5 = TexturePtr(new Texture(imgBallOFF, false)); ballTexture4 = TexturePtr(new Texture(imgBallOFF, false)); ballTexture3 = TexturePtr(new Texture(imgBallOFF, false)); ballTexture2 = TexturePtr(new Texture(imgBallOFF, false)); ballTexture1 = TexturePtr(new Texture(imgBallUSE, false)); } else if (ball_counts == 1) { ballTexture5 = TexturePtr(new Texture(imgBallOFF, false)); ballTexture4 = TexturePtr(new Texture(imgBallOFF, false)); ballTexture3 = TexturePtr(new Texture(imgBallOFF, false)); ballTexture2 = TexturePtr(new Texture(imgBallOFF, false)); ballTexture1 = TexturePtr(new Texture(imgBallOFF, false)); } Rect skullRect = Rect(backgroundRect.x() - countPos, backgroundRect.y() - 25, ballTexture1->getSize()); Rect skullRect2 = Rect(backgroundRect.x() - countPos2, backgroundRect.y() - 25, ballTexture1->getSize()); Rect skullRect3 = Rect(backgroundRect.x() - countPos3, backgroundRect.y() - 25, ballTexture1->getSize()); Rect skullRect4 = Rect(backgroundRect.x() - countPos4, backgroundRect.y() - 25, ballTexture1->getSize()); Rect skullRect5 = Rect(backgroundRect.x() - countPos5, backgroundRect.y() - 25, ballTexture1->getSize()); g_painter->setOpacity(0.8f); g_painter->drawTexturedRect(skullRect, ballTexture1); g_painter->drawTexturedRect(skullRect2, ballTexture2); g_painter->drawTexturedRect(skullRect3, ballTexture3); g_painter->drawTexturedRect(skullRect4, ballTexture4); g_painter->drawTexturedRect(skullRect5, ballTexture5); } else if (duel_mode == 6) { int countPos = 21 - 10; int countPos2 = 21 - 20; int countPos3 = 21 - 30; int countPos4 = 21 - 40; int countPos5 = 21 - 50; int countPos6 = 21 - 60; if (ball_counts == 12) { ballTexture6 = TexturePtr(new Texture(imgBallUSE, false)); } else if (ball_counts == 11) { ballTexture6 = TexturePtr(new Texture(imgBallOFF, false)); } else if (ball_counts == 10) { ballTexture6 = TexturePtr(new Texture(imgBallOFF, false)); ballTexture5 = TexturePtr(new Texture(imgBallUSE, false)); } else if (ball_counts == 9) { ballTexture6 = TexturePtr(new Texture(imgBallOFF, false)); ballTexture5 = TexturePtr(new Texture(imgBallOFF, false)); } else if (ball_counts == ? { ballTexture6 = TexturePtr(new Texture(imgBallOFF, false)); ballTexture5 = TexturePtr(new Texture(imgBallOFF, false)); ballTexture4 = TexturePtr(new Texture(imgBallUSE, false)); } else if (ball_counts == 7) { ballTexture6 = TexturePtr(new Texture(imgBallOFF, false)); ballTexture5 = TexturePtr(new Texture(imgBallOFF, false)); ballTexture4 = TexturePtr(new Texture(imgBallOFF, false)); } else if (ball_counts == 6) { ballTexture6 = TexturePtr(new Texture(imgBallOFF, false)); ballTexture5 = TexturePtr(new Texture(imgBallOFF, false)); ballTexture4 = TexturePtr(new Texture(imgBallOFF, false)); ballTexture3 = TexturePtr(new Texture(imgBallUSE, false)); } else if (ball_counts == 5) { ballTexture6 = TexturePtr(new Texture(imgBallOFF, false)); ballTexture5 = TexturePtr(new Texture(imgBallOFF, false)); ballTexture4 = TexturePtr(new Texture(imgBallOFF, false)); ballTexture3 = TexturePtr(new Texture(imgBallOFF, false)); } else if (ball_counts == 4) { ballTexture6 = TexturePtr(new Texture(imgBallOFF, false)); ballTexture5 = TexturePtr(new Texture(imgBallOFF, false)); ballTexture4 = TexturePtr(new Texture(imgBallOFF, false)); ballTexture3 = TexturePtr(new Texture(imgBallOFF, false)); ballTexture2 = TexturePtr(new Texture(imgBallUSE, false)); } else if (ball_counts == 3) { ballTexture6 = TexturePtr(new Texture(imgBallOFF, false)); ballTexture5 = TexturePtr(new Texture(imgBallOFF, false)); ballTexture4 = TexturePtr(new Texture(imgBallOFF, false)); ballTexture3 = TexturePtr(new Texture(imgBallOFF, false)); ballTexture2 = TexturePtr(new Texture(imgBallOFF, false)); } else if (ball_counts == 2) { ballTexture6 = TexturePtr(new Texture(imgBallOFF, false)); ballTexture5 = TexturePtr(new Texture(imgBallOFF, false)); ballTexture4 = TexturePtr(new Texture(imgBallOFF, false)); ballTexture3 = TexturePtr(new Texture(imgBallOFF, false)); ballTexture2 = TexturePtr(new Texture(imgBallOFF, false)); ballTexture1 = TexturePtr(new Texture(imgBallUSE, false)); } else if (ball_counts == 1) { ballTexture6 = TexturePtr(new Texture(imgBallOFF, false)); ballTexture5 = TexturePtr(new Texture(imgBallOFF, false)); ballTexture4 = TexturePtr(new Texture(imgBallOFF, false)); ballTexture3 = TexturePtr(new Texture(imgBallOFF, false)); ballTexture2 = TexturePtr(new Texture(imgBallOFF, false)); ballTexture1 = TexturePtr(new Texture(imgBallOFF, false)); } Rect skullRect = Rect(backgroundRect.x() - countPos, backgroundRect.y() - 25, ballTexture1->getSize()); Rect skullRect2 = Rect(backgroundRect.x() - countPos2, backgroundRect.y() - 25, ballTexture1->getSize()); Rect skullRect3 = Rect(backgroundRect.x() - countPos3, backgroundRect.y() - 25, ballTexture1->getSize()); Rect skullRect4 = Rect(backgroundRect.x() - countPos4, backgroundRect.y() - 25, ballTexture1->getSize()); Rect skullRect5 = Rect(backgroundRect.x() - countPos5, backgroundRect.y() - 25, ballTexture1->getSize()); Rect skullRect6 = Rect(backgroundRect.x() - countPos6, backgroundRect.y() - 25, ballTexture1->getSize()); g_painter->setOpacity(0.8f); g_painter->drawTexturedRect(skullRect, ballTexture1); g_painter->drawTexturedRect(skullRect2, ballTexture2); g_painter->drawTexturedRect(skullRect3, ballTexture3); g_painter->drawTexturedRect(skullRect4, ballTexture4); g_painter->drawTexturedRect(skullRect5, ballTexture5); g_painter->drawTexturedRect(skullRect6, ballTexture6); } /*for (int i = 0; i < duel_mode; i++) { int count = 23 - (10 * i); TexturePtr ballTexture = TexturePtr(new Texture(imgBall, false)); if(i == 4) ballTexture = TexturePtr(new Texture(imgBallUSE, false)); else if(i == 5) ballTexture = TexturePtr(new Texture(imgBallOFF, false)); Rect skullRect = Rect(backgroundRect.x() - count, backgroundRect.y() - 25, ballTexture->getSize()); g_painter->setOpacity(0.8f); g_painter->drawTexturedRect(skullRect, ballTexture); } */ g_painter->setOpacity(1.0f); } 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); } if(m_icon != Otc::NpcIconNone && m_iconTexture) { g_painter->setColor(Color::white); Rect iconRect = Rect(backgroundRect.x() + 13.5 + 12, backgroundRect.y() + 5, m_iconTexture->getSize()); g_painter->drawTexturedRect(iconRect, m_iconTexture); } } 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; if(m_walkFinishAnimEvent) { m_walkFinishAnimEvent->cancel(); m_walkFinishAnimEvent = nullptr; } // 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; // stops the walk right away terminateWalk(); } void Creature::jump(int height, int duration) { if(!m_jumpOffset.isNull()) return; m_jumpTimer.restart(); m_jumpHeight = height; m_jumpDuration = duration; updateJump(); } void Creature::updateJump() { int t = m_jumpTimer.ticksElapsed(); double a = -4 * m_jumpHeight / (m_jumpDuration * m_jumpDuration); double b = +4 * m_jumpHeight / (m_jumpDuration); double height = a*t*t + b*t; int roundHeight = stdext::round(height); int halfJumpDuration = m_jumpDuration / 2; // schedules next update if(m_jumpTimer.ticksElapsed() < m_jumpDuration) { m_jumpOffset = PointF(height, height); int diff = 0; if(m_jumpTimer.ticksElapsed() < halfJumpDuration) diff = 1; else if(m_jumpTimer.ticksElapsed() > halfJumpDuration) diff = -1; int nextT, i = 1; do { nextT = stdext::round((-b + std::sqrt(std::max<int>(b*b + 4*a*(roundHeight+diff*i), 0.0)) * diff) / (2*a)); ++i; if(nextT < halfJumpDuration) diff = 1; else if(nextT > halfJumpDuration) diff = -1; } while(nextT - m_jumpTimer.ticksElapsed() == 0 && i < 3); auto self = static_self_cast<Creature>(); g_dispatcher.scheduleEvent([self] { self->updateJump(); }, nextT - m_jumpTimer.ticksElapsed()); } else m_jumpOffset = PointF(0, 0); } 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::onDeath() { callLuaField("onDeath"); } void Creature::updateWalkAnimation(int totalPixelsWalked) { // update outfit animation if(m_outfit.getCategory() != ThingCategoryCreature) return; int footAnimPhases = getAnimationPhases() - 1; int footDelay = getStepDuration(true) / 3; // Since mount is a different outfit we need to get the mount animation phases if(m_outfit.getMount() != 0) { ThingType *type = g_things.rawGetThingType(m_outfit.getMount(), m_outfit.getCategory()); footAnimPhases = type->getAnimationPhases() - 1; } if(footAnimPhases == 0) m_walkAnimationPhase = 0; else if(m_footStepDrawn && m_footTimer.ticksElapsed() >= footDelay && totalPixelsWalked < 32) { m_footStep++; m_walkAnimationPhase = 1 + (m_footStep % footAnimPhases); m_footStepDrawn = false; m_footTimer.restart(); } else if(m_walkAnimationPhase == 0 && totalPixelsWalked < 32) { m_walkAnimationPhase = 1 + (m_footStep % footAnimPhases); } if(totalPixelsWalked == 32 && !m_walkFinishAnimEvent) { auto self = static_self_cast<Creature>(); m_walkFinishAnimEvent = g_dispatcher.scheduleEvent([self] { if(!self->m_walking || self->m_walkTimer.ticksElapsed() >= self->getStepDuration(true)) self->m_walkAnimationPhase = 0; self->m_walkFinishAnimEvent = nullptr; }, std::min<int>(footDelay, 200)); } } 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.notificateTileUpdate(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<int>(m_walkTimer.ticksElapsed() / walkTicksPerPixel, 32.0f); // needed for paralyze effect m_walkedPixels = std::max<int>(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; // reset walk animation states m_walkOffset = Point(0,0); m_walkAnimationPhase = 0; } void Creature::setName(const std::string& name) { m_nameCache.setText(name); m_name = name; } void Creature::setHealthPercent(uint8 healthPercent) { if(healthPercent > 92) m_informationColor = Color(0x00, 0xBC, 0x00); else if(healthPercent > 60) m_informationColor = Color(0x50, 0xA1, 0x50); else if(healthPercent > 30) m_informationColor = Color(0xA1, 0xA1, 0x00); else if(healthPercent > ? m_informationColor = Color(0xBF, 0x0A, 0x0A); else if(healthPercent > 3) m_informationColor = Color(0x91, 0x0F, 0x0F); else m_informationColor = Color(0x85, 0x0C, 0x0C); m_healthPercent = healthPercent; callLuaField("onHealthPercentChange", healthPercent); if(healthPercent <= 0) onDeath(); } void Creature::setDirection(Otc::Direction direction) { assert(direction != Otc::InvalidDirection); m_direction = direction; } void Creature::setOutfit(const Outfit& outfit) { Outfit oldOutfit = m_outfit; if(outfit.getCategory() != ThingCategoryCreature) { if(!g_things.isValidDatId(outfit.getAuxId(), outfit.getCategory())) return; m_outfit.setAuxId(outfit.getAuxId()); m_outfit.setCategory(outfit.getCategory()); m_outfit2.setAuxId(outfit.getAuxId()); m_outfit2.setCategory(outfit.getCategory()); } else { if(outfit.getId() > 0 && !g_things.isValidDatId(outfit.getId(), ThingCategoryCreature)) return; m_outfit = outfit; m_outfit2 = outfit; } m_walkAnimationPhase = 0; // might happen when player is walking and outfit is changed. callLuaField("onOutfitChange", m_outfit, oldOutfit); } void Creature::setOutfitColor(const Color& color, int duration) { if(m_outfitColorUpdateEvent) { m_outfitColorUpdateEvent->cancel(); m_outfitColorUpdateEvent = nullptr; } if(duration > 0) { Color delta = (color - m_outfitColor) / (float)duration; m_outfitColorTimer.restart(); updateOutfitColor(m_outfitColor, color, delta, duration); } else m_outfitColor = color; } void Creature::updateOutfitColor(Color color, Color finalColor, Color delta, int duration) { if(m_outfitColorTimer.ticksElapsed() < duration) { m_outfitColor = color + delta * m_outfitColorTimer.ticksElapsed(); auto self = static_self_cast<Creature>(); m_outfitColorUpdateEvent = g_dispatcher.scheduleEvent([=] { self->updateOutfitColor(color, finalColor, delta, duration); }, 100); } else { m_outfitColor = finalColor; } } 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::setBaseSpeed(double baseSpeed) { if(m_baseSpeed != baseSpeed) { double oldBaseSpeed = m_baseSpeed; m_baseSpeed = baseSpeed; callLuaField("onBaseSpeedChange", baseSpeed, oldBaseSpeed); } } 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::setIcon(uint8 icon) { m_icon = icon; callLuaField("onIconChange", m_icon); } 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::setIconTexture(const std::string& filename) { m_iconTexture = 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, Otc::Direction dir) { int speed = m_speed; if(speed < 1) return 0; if(g_game.getFeature(Otc::GameNewSpeedLaw)) speed *= 2; int groundSpeed = 0; Position tilePos; if(dir == Otc::InvalidDirection) tilePos = m_lastStepToPosition; else tilePos = m_position.translatedToDirection(dir); 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<int>(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.getClientVersion() >= 900) interval = (interval / g_game.getServerBeat()) * g_game.getServerBeat(); float factor = 3; if(g_game.getClientVersion() <= 810) factor = 2; interval = std::max<int>(interval, g_game.getServerBeat()); if(!ignoreDiagonal && (m_lastStepDirection == Otc::NorthWest || m_lastStepDirection == Otc::NorthEast || m_lastStepDirection == Otc::SouthWest || m_lastStepDirection == Otc::SouthEast)) interval *= factor; 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; if(m_outfit.getMount() != 0) { auto datType = g_things.rawGetThingType(m_outfit.getMount(), ThingCategoryCreature); return datType->getDisplacementX(); } return Thing::getDisplacementX(); } int Creature::getDisplacementY() { if(m_outfit.getCategory() == ThingCategoryEffect) return 8; else if(m_outfit.getCategory() == ThingCategoryItem) return 0; if(m_outfit.getMount() != 0) { auto datType = g_things.rawGetThingType(m_outfit.getMount(), ThingCategoryCreature); return datType->getDisplacementY(); } 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<int>(exactSize, Thing::getExactSize(layer, xPattern, yPattern, zPattern, animationPhase)); } return exactSize; } const ThingTypePtr& Creature::getThingType() { return g_things.getThingType(m_outfit.getId(), ThingCategoryCreature); } const ThingTypePtr& Creature::getThingType2() { return g_things.getThingType2(m_outfit.getId(), ThingCategoryCreature); } ThingType* Creature::rawGetThingType() { if (!iniciou) { novaOutType = g_things.getThingTypeInSecondList(m_outfit2.getId(), ThingCategoryCreature); iniciou = true; } return g_things.rawGetThingType(m_outfit.getId(), ThingCategoryCreature); } ThingType* Creature::rawGetThingType2() { if (!iniciou) { novaOutType = g_things.getThingTypeInSecondList(m_outfit2.getId(), ThingCategoryCreature); iniciou = true; } return novaOutType; } Link para o comentário Compartilhar em outros sites More sharing options...
OrionX 0 Postado Julho 13, 2018 Share Postado Julho 13, 2018 Desculpe reviver o post, mas não estou achando os seguintes comandos na source, poderia me ajudar? Link para o comentário Compartilhar em outros sites More sharing options...
Visitante Postado Julho 27, 2018 Share Postado Julho 27, 2018 Em 13/07/2018 em 16:09, OrionX disse: Desculpe reviver o post, mas não estou achando os seguintes comandos na source, poderia me ajudar? quais ? Em 11/07/2018 em 11:05, boxxer321 disse: não achei essa linha no meu creature.cpp g_painter->drawBoundingRect(Rect(dest + (animationOffset - getDisplacement() + 2)*scaleFactor, Size(28, 28)*scaleFactor), std::max<int>((int)(2*scaleFactor), 1)); se puder dar uma olhada: Mostrar conteúdo oculto /* * Copyright (c) 2010-2017 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/stdext/format.h> #include <framework/graphics/graphics.h> #include <framework/core/eventdispatcher.h> #include <framework/core/clock.h> #include <framework/graphics/paintershaderprogram.h> #include <framework/graphics/ogl/painterogl2_shadersources.h> #include <framework/graphics/texturemanager.h> #include <framework/graphics/framebuffermanager.h> #include <framework/graphics/image.h> #include "spritemanager.h" #include <framework/core/resourcemanager.h> #include <framework/core/filestream.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_icon = Otc::NpcIconNone; 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); m_outfitColor = Color::white; } 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) { EffectPtr effect = EffectPtr(new Effect()); effect->setId(819); g_painter->setColor(m_timedSquareColor); Rect rect = Rect(dest + (animationOffset - getDisplacement())*scaleFactor, Size(Otc::TILE_PIXELS, Otc::TILE_PIXELS)*scaleFactor); g_painter->drawTexturedRect(rect, effect->getThingType()->getTextureEX(0)); g_painter->setColor(Color::white); g_painter->setColor(Color::white); } if(m_showStaticSquare && animate) { EffectPtr effect = EffectPtr(new Effect()); effect->setId(819); g_painter->setColor(m_staticSquareColor); Rect rect = Rect(dest + (animationOffset - getDisplacement())*scaleFactor, Size(Otc::TILE_PIXELS, Otc::TILE_PIXELS)*scaleFactor); g_painter->drawTexturedRect(rect, effect->getThingType()->getTextureEX(0)); 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, 3); if(light.color == 0 || light.color > 215) light.color = 215; } if(light.intensity > 0) lightView->addLightSource(dest + (animationOffset + Point(16,16)) * scaleFactor, scaleFactor, light); } } int countTest = 0; void Creature::internalDrawOutfit(Point dest, float scaleFactor, bool animateWalk, bool animateIdle, Otc::Direction direction, LightView *lightView) { g_painter->setColor(m_outfitColor); // 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; PointF jumpOffset = m_jumpOffset * scaleFactor; dest -= Point(stdext::round(jumpOffset.x), stdext::round(jumpOffset.y)); // 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 = getThingType(); if(m_skull >= 1){ float initEffe = 0.4f, endEffe = 0.6f; int exactSize = getExactSize(); double scaleMult = 1.12, axsX = 0.97, axsY = 1.2; // ate 42 de exactSize Color azul = Color(0.0f, 128.0, 255.0, 1.0f), verde = Color(51, 255, 51), laranja = Color(255, 102, 0), azulCya = Color(51, 204, 255), white = Color::white, viliota = Color(102, 0, 255), roxa = Color(153, 0, 204), redScarlat = Color(230, 0, 0), amarelo = Color(255, 255, 0), preto = Color::black, rosa = Color(255, 51, 153), jeaneSoisQuoi = Color(0, 102, 102), cou = Color(204, 51, 0); Color auraColor = azul;// azul //Color config 1 = black, 2 = blue, 3 = green, 4 = pink, 5 = orange if(m_skull == 2) auraColor = verde; else if(m_skull == 3) auraColor = laranja; else if (m_skull == 4) auraColor = azulCya; else if (m_skull == 5) auraColor = white; else if (m_skull == 6) auraColor = viliota; else if (m_skull == 7) auraColor = roxa; else if (m_skull == ? auraColor = redScarlat; else if (m_skull == 9) auraColor = amarelo; else if (m_skull == 10) { initEffe = 0.7f; endEffe = 0.9f; auraColor = preto; } else if (m_skull == 11) { auraColor = rosa; initEffe = 0.3f; endEffe = 0.7f; } else if (m_skull == 12) auraColor = jeaneSoisQuoi; else if (m_skull == 13) auraColor = cou; if(exactSize == 52) { // tamanho das sprites axsY = 0.92; }else if(exactSize == 32) { // tamanho das sprites scaleMult = 1.16; axsX = 0.94; axsY = 0.92; } Point p = Point(dest.x-axsX, dest.y-axsY); //Rect rect = Rect(p.x, p.y, datType->getTexture(animationPhase)->getSize()); countTest++; //colored raibow aura if (m_skull == 14) { if (countTest <= 40) auraColor = white; else if (countTest >= 41 && countTest <= 80) auraColor = redScarlat; else if (countTest >= 81 && countTest <= 120) auraColor = verde; else if (countTest >= 121 && countTest <= 160) auraColor = laranja; else if (countTest >= 161 && countTest <= 200) auraColor = azul; else if (countTest >= 201 && countTest <= 240) auraColor = amarelo; else if (countTest >= 241) countTest = 0; }else { if (countTest <= 60) { g_painter->setOpacity(initEffe); } else if (countTest >= 61 && countTest <= 110) { g_painter->setOpacity(endEffe); } else if (countTest >= 111) countTest = 0; } g_painter->setColor(auraColor); datType->drawEX(p, scaleFactor*scaleMult, 0, xPattern, yPattern, zPattern, animationPhase, yPattern == 0 ? lightView : nullptr); //g_painter->drawTexturedRect(rect, datType->getTexture(animationPhase, true)); g_painter->setOpacity(1.0f); } // if(m_skull >= 1 && m_skullTexture){ // g_painter->setOpacity(0.7f); //} g_painter->setColor(m_outfitColor); 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<int>(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<int>(animationPhase+1, animationPhases); type->draw(dest - (getDisplacement() * scaleFactor), scaleFactor, 0, 0, 0, 0, animationPhase, lightView); } g_painter->resetColor(); g_painter->setOpacity(1.0f); } 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(); int frameSize; if(!resize) frameSize = std::max<int>(exactSize * 0.75f, 2 * Otc::TILE_PIXELS * 0.75f); else if(!(frameSize = exactSize)) return; if(g_graphics.canUseFBO()) { const FrameBufferPtr& outfitBuffer = g_framebuffers.getTemporaryFrameBuffer(); outfitBuffer->resize(Size(frameSize, frameSize)); outfitBuffer->bind(); g_painter->setAlphaWriting(true); g_painter->clear(Color::alpha); internalDrawOutfit(Point(frameSize - Otc::TILE_PIXELS, frameSize - Otc::TILE_PIXELS) + getDisplacement(), 1, false, true, Otc::South); outfitBuffer->release(); outfitBuffer->draw(destRect, Rect(0,0,frameSize,frameSize)); } else { float scaleFactor = destRect.width() / (float)frameSize; 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, int drawFlags) { if(m_healthPercent < 1 || m_outfit.getId() == 84) // creature is dead return; Color fillColor = Color(96, 96, 96); if(!useGray) fillColor = m_informationColor; int exactSize = getExactSize(); int d = 0, dx = 0; if(exactSize <= 34) d = 5; else if(exactSize >= 35 && exactSize <= 48) d = 15; else if(exactSize >= 49 && exactSize <= 52) d = 25; else if(exactSize >= 53 && exactSize <= 57) d = 30; else if(exactSize >= 58 && exactSize <= 69) d = 25; else if(exactSize == 74) d = 37; dx = d /2; if(exactSize <= 34) dx = 17; // calculate main rects Rect backgroundRect = Rect(point.x - dx, point.y - d, 40, 6); backgroundRect.bind(parentRect); Size nameSize = m_nameCache.getTextSize(); Rect textRect = Rect(point.x - nameSize.width() / 2, point.y-14, 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(); int calc = ((m_healthPercent / 100.0) * 40.0) + 60; std::string nameBar = std::to_string(calc); if (calc == 100) nameBar = "full"; // draw if(g_game.getFeature(Otc::GameBlueNpcNameColor) && isNpc() && m_healthPercent == 100 && !useGray) fillColor = Color(0x66, 0xcc, 0xff); if(drawFlags & Otc::DrawBars && (!isNpc() || !g_game.getFeature(Otc::GameHideNpcNames))) { g_painter->setColor(Color::white); ImagePtr backgroundLifeBar = Image::load("data/images/game/lifebar/background"); TexturePtr bgLifeBar = TexturePtr(new Texture(backgroundLifeBar, false)); //g_painter->drawFilledRect(backgroundRect); g_painter->drawTexturedRect(backgroundRect, bgLifeBar); ImagePtr healthLifeBar = Image::load("data/images/game/lifebar/" + nameBar); TexturePtr lifeBar = TexturePtr(new Texture(healthLifeBar, false)); g_painter->drawTexturedRect(healthRect, lifeBar); //g_painter->drawFilledRect(healthRect); } if(drawFlags & Otc::DrawNames) { g_painter->setColor(Color(213, 213, 0)); //m_nameCache.setText(std::to_string(m_outfit.getId())); //m_nameCache.set m_nameCache.draw(textRect); } if (m_skull >= 50 && m_skull <= 56) { // 0 = on | 1 = use | 2 = off // 50 | 49 | 48 //0 0 0 0 0 0 | 0 0 0 0 0 1 | 0 0 0 0 1 2 // g_painter->setColor(Color::white); ImagePtr imgBallON = Image::load("data/images/game/duel/pokeball_on"); ImagePtr imgBallOFF = Image::load("data/images/game/duel/pokeball_off"); ImagePtr imgBallUSE = Image::load("data/images/game/duel/pokeball_use"); int duel_mode = m_skull - 50, ball_counts = m_emblem - 50; TexturePtr ballTexture1 = TexturePtr(new Texture(imgBallON, false)); TexturePtr ballTexture2 = TexturePtr(new Texture(imgBallON, false)); TexturePtr ballTexture3 = TexturePtr(new Texture(imgBallON, false)); TexturePtr ballTexture4 = TexturePtr(new Texture(imgBallON, false)); TexturePtr ballTexture5 = TexturePtr(new Texture(imgBallON, false)); TexturePtr ballTexture6 = TexturePtr(new Texture(imgBallON, false)); if (duel_mode == 1) { int countPos = 23 - (10 * 3); if (ball_counts == 1) ballTexture1 = TexturePtr(new Texture(imgBallUSE, false)); ballTexture1->setSmooth(true); Rect skullRect = Rect(backgroundRect.x() - countPos, backgroundRect.y() - 25, ballTexture1->getSize()); g_painter->setOpacity(0.8f); g_painter->drawTexturedRect(skullRect, ballTexture1); } else if (duel_mode == 2) { int countPos = 8 - 10; int countPos2 = 8 - 20; if (ball_counts == 4) { ballTexture2 = TexturePtr(new Texture(imgBallUSE, false)); } else if (ball_counts == 3) { ballTexture2 = TexturePtr(new Texture(imgBallOFF, false)); } else if (ball_counts == 2) { ballTexture2 = TexturePtr(new Texture(imgBallOFF, false)); ballTexture1 = TexturePtr(new Texture(imgBallUSE, false)); } else if (ball_counts == 1) { ballTexture2 = TexturePtr(new Texture(imgBallOFF, false)); ballTexture1 = TexturePtr(new Texture(imgBallOFF, false)); } Rect skullRect = Rect(backgroundRect.x() - countPos, backgroundRect.y() - 25, ballTexture1->getSize()); Rect skullRect2 = Rect(backgroundRect.x() - countPos2, backgroundRect.y() - 25, ballTexture1->getSize()); g_painter->setOpacity(0.8f); g_painter->drawTexturedRect(skullRect, ballTexture1); g_painter->drawTexturedRect(skullRect2, ballTexture2); } else if (duel_mode == 3) { int countPos = 13 - 10; int countPos2 = 13 - 20; int countPos3 = 13 - 30; if (ball_counts == 6) { ballTexture3 = TexturePtr(new Texture(imgBallUSE, false)); } else if (ball_counts == 5) { ballTexture3 = TexturePtr(new Texture(imgBallOFF, false)); } else if (ball_counts == 4) { ballTexture3 = TexturePtr(new Texture(imgBallOFF, false)); ballTexture2 = TexturePtr(new Texture(imgBallUSE, false)); } else if (ball_counts == 3) { ballTexture3 = TexturePtr(new Texture(imgBallOFF, false)); ballTexture2 = TexturePtr(new Texture(imgBallOFF, false)); } else if (ball_counts == 2) { ballTexture3 = TexturePtr(new Texture(imgBallOFF, false)); ballTexture2 = TexturePtr(new Texture(imgBallOFF, false)); ballTexture1 = TexturePtr(new Texture(imgBallUSE, false)); } else if (ball_counts == 1) { ballTexture3 = TexturePtr(new Texture(imgBallOFF, false)); ballTexture2 = TexturePtr(new Texture(imgBallOFF, false)); ballTexture1 = TexturePtr(new Texture(imgBallOFF, false)); } Rect skullRect = Rect(backgroundRect.x() - countPos, backgroundRect.y() - 25, ballTexture1->getSize()); Rect skullRect2 = Rect(backgroundRect.x() - countPos2, backgroundRect.y() - 25, ballTexture1->getSize()); Rect skullRect3 = Rect(backgroundRect.x() - countPos3, backgroundRect.y() - 25, ballTexture1->getSize()); g_painter->setOpacity(0.8f); g_painter->drawTexturedRect(skullRect, ballTexture1); g_painter->drawTexturedRect(skullRect2, ballTexture2); g_painter->drawTexturedRect(skullRect3, ballTexture3); } else if (duel_mode == 4) { int countPos = 15 - 10; int countPos2 = 15 - 20; int countPos3 = 15 - 30; int countPos4 = 15 - 40; if (ball_counts == ? { ballTexture4 = TexturePtr(new Texture(imgBallUSE, false)); } else if (ball_counts == 7) { ballTexture4 = TexturePtr(new Texture(imgBallOFF, false)); } else if (ball_counts == 6) { ballTexture4 = TexturePtr(new Texture(imgBallOFF, false)); ballTexture3 = TexturePtr(new Texture(imgBallUSE, false)); } else if (ball_counts == 5) { ballTexture4 = TexturePtr(new Texture(imgBallOFF, false)); ballTexture3 = TexturePtr(new Texture(imgBallOFF, false)); } else if (ball_counts == 4) { ballTexture4 = TexturePtr(new Texture(imgBallOFF, false)); ballTexture3 = TexturePtr(new Texture(imgBallOFF, false)); ballTexture2 = TexturePtr(new Texture(imgBallUSE, false)); } else if (ball_counts == 3) { ballTexture4 = TexturePtr(new Texture(imgBallOFF, false)); ballTexture3 = TexturePtr(new Texture(imgBallOFF, false)); ballTexture2 = TexturePtr(new Texture(imgBallOFF, false)); } else if (ball_counts == 2) { ballTexture4 = TexturePtr(new Texture(imgBallOFF, false)); ballTexture3 = TexturePtr(new Texture(imgBallOFF, false)); ballTexture2 = TexturePtr(new Texture(imgBallOFF, false)); ballTexture1 = TexturePtr(new Texture(imgBallUSE, false)); } else if (ball_counts == 1) { ballTexture4 = TexturePtr(new Texture(imgBallOFF, false)); ballTexture3 = TexturePtr(new Texture(imgBallOFF, false)); ballTexture2 = TexturePtr(new Texture(imgBallOFF, false)); ballTexture1 = TexturePtr(new Texture(imgBallOFF, false)); } Rect skullRect = Rect(backgroundRect.x() - countPos, backgroundRect.y() - 25, ballTexture1->getSize()); Rect skullRect2 = Rect(backgroundRect.x() - countPos2, backgroundRect.y() - 25, ballTexture1->getSize()); Rect skullRect3 = Rect(backgroundRect.x() - countPos3, backgroundRect.y() - 25, ballTexture1->getSize()); Rect skullRect4 = Rect(backgroundRect.x() - countPos4, backgroundRect.y() - 25, ballTexture1->getSize()); g_painter->setOpacity(0.8f); g_painter->drawTexturedRect(skullRect, ballTexture1); g_painter->drawTexturedRect(skullRect2, ballTexture2); g_painter->drawTexturedRect(skullRect3, ballTexture3); g_painter->drawTexturedRect(skullRect4, ballTexture4); } else if (duel_mode == 5) { int countPos = 18 - 10; int countPos2 = 18 - 20; int countPos3 = 18 - 30; int countPos4 = 18 - 40; int countPos5 = 18 - 50; if (ball_counts == 10) { ballTexture5 = TexturePtr(new Texture(imgBallUSE, false)); } else if (ball_counts == 9) { ballTexture5 = TexturePtr(new Texture(imgBallOFF, false)); } else if (ball_counts == ? { ballTexture5 = TexturePtr(new Texture(imgBallOFF, false)); ballTexture4 = TexturePtr(new Texture(imgBallUSE, false)); } else if (ball_counts == 7) { ballTexture5 = TexturePtr(new Texture(imgBallOFF, false)); ballTexture4 = TexturePtr(new Texture(imgBallOFF, false)); } else if (ball_counts == 6) { ballTexture5 = TexturePtr(new Texture(imgBallOFF, false)); ballTexture4 = TexturePtr(new Texture(imgBallOFF, false)); ballTexture3 = TexturePtr(new Texture(imgBallUSE, false)); } else if (ball_counts == 5) { ballTexture5 = TexturePtr(new Texture(imgBallOFF, false)); ballTexture4 = TexturePtr(new Texture(imgBallOFF, false)); ballTexture3 = TexturePtr(new Texture(imgBallOFF, false)); } else if (ball_counts == 4) { ballTexture5 = TexturePtr(new Texture(imgBallOFF, false)); ballTexture4 = TexturePtr(new Texture(imgBallOFF, false)); ballTexture3 = TexturePtr(new Texture(imgBallOFF, false)); ballTexture2 = TexturePtr(new Texture(imgBallUSE, false)); } else if (ball_counts == 3) { ballTexture5 = TexturePtr(new Texture(imgBallOFF, false)); ballTexture4 = TexturePtr(new Texture(imgBallOFF, false)); ballTexture3 = TexturePtr(new Texture(imgBallOFF, false)); ballTexture2 = TexturePtr(new Texture(imgBallOFF, false)); } else if (ball_counts == 2) { ballTexture5 = TexturePtr(new Texture(imgBallOFF, false)); ballTexture4 = TexturePtr(new Texture(imgBallOFF, false)); ballTexture3 = TexturePtr(new Texture(imgBallOFF, false)); ballTexture2 = TexturePtr(new Texture(imgBallOFF, false)); ballTexture1 = TexturePtr(new Texture(imgBallUSE, false)); } else if (ball_counts == 1) { ballTexture5 = TexturePtr(new Texture(imgBallOFF, false)); ballTexture4 = TexturePtr(new Texture(imgBallOFF, false)); ballTexture3 = TexturePtr(new Texture(imgBallOFF, false)); ballTexture2 = TexturePtr(new Texture(imgBallOFF, false)); ballTexture1 = TexturePtr(new Texture(imgBallOFF, false)); } Rect skullRect = Rect(backgroundRect.x() - countPos, backgroundRect.y() - 25, ballTexture1->getSize()); Rect skullRect2 = Rect(backgroundRect.x() - countPos2, backgroundRect.y() - 25, ballTexture1->getSize()); Rect skullRect3 = Rect(backgroundRect.x() - countPos3, backgroundRect.y() - 25, ballTexture1->getSize()); Rect skullRect4 = Rect(backgroundRect.x() - countPos4, backgroundRect.y() - 25, ballTexture1->getSize()); Rect skullRect5 = Rect(backgroundRect.x() - countPos5, backgroundRect.y() - 25, ballTexture1->getSize()); g_painter->setOpacity(0.8f); g_painter->drawTexturedRect(skullRect, ballTexture1); g_painter->drawTexturedRect(skullRect2, ballTexture2); g_painter->drawTexturedRect(skullRect3, ballTexture3); g_painter->drawTexturedRect(skullRect4, ballTexture4); g_painter->drawTexturedRect(skullRect5, ballTexture5); } else if (duel_mode == 6) { int countPos = 21 - 10; int countPos2 = 21 - 20; int countPos3 = 21 - 30; int countPos4 = 21 - 40; int countPos5 = 21 - 50; int countPos6 = 21 - 60; if (ball_counts == 12) { ballTexture6 = TexturePtr(new Texture(imgBallUSE, false)); } else if (ball_counts == 11) { ballTexture6 = TexturePtr(new Texture(imgBallOFF, false)); } else if (ball_counts == 10) { ballTexture6 = TexturePtr(new Texture(imgBallOFF, false)); ballTexture5 = TexturePtr(new Texture(imgBallUSE, false)); } else if (ball_counts == 9) { ballTexture6 = TexturePtr(new Texture(imgBallOFF, false)); ballTexture5 = TexturePtr(new Texture(imgBallOFF, false)); } else if (ball_counts == ? { ballTexture6 = TexturePtr(new Texture(imgBallOFF, false)); ballTexture5 = TexturePtr(new Texture(imgBallOFF, false)); ballTexture4 = TexturePtr(new Texture(imgBallUSE, false)); } else if (ball_counts == 7) { ballTexture6 = TexturePtr(new Texture(imgBallOFF, false)); ballTexture5 = TexturePtr(new Texture(imgBallOFF, false)); ballTexture4 = TexturePtr(new Texture(imgBallOFF, false)); } else if (ball_counts == 6) { ballTexture6 = TexturePtr(new Texture(imgBallOFF, false)); ballTexture5 = TexturePtr(new Texture(imgBallOFF, false)); ballTexture4 = TexturePtr(new Texture(imgBallOFF, false)); ballTexture3 = TexturePtr(new Texture(imgBallUSE, false)); } else if (ball_counts == 5) { ballTexture6 = TexturePtr(new Texture(imgBallOFF, false)); ballTexture5 = TexturePtr(new Texture(imgBallOFF, false)); ballTexture4 = TexturePtr(new Texture(imgBallOFF, false)); ballTexture3 = TexturePtr(new Texture(imgBallOFF, false)); } else if (ball_counts == 4) { ballTexture6 = TexturePtr(new Texture(imgBallOFF, false)); ballTexture5 = TexturePtr(new Texture(imgBallOFF, false)); ballTexture4 = TexturePtr(new Texture(imgBallOFF, false)); ballTexture3 = TexturePtr(new Texture(imgBallOFF, false)); ballTexture2 = TexturePtr(new Texture(imgBallUSE, false)); } else if (ball_counts == 3) { ballTexture6 = TexturePtr(new Texture(imgBallOFF, false)); ballTexture5 = TexturePtr(new Texture(imgBallOFF, false)); ballTexture4 = TexturePtr(new Texture(imgBallOFF, false)); ballTexture3 = TexturePtr(new Texture(imgBallOFF, false)); ballTexture2 = TexturePtr(new Texture(imgBallOFF, false)); } else if (ball_counts == 2) { ballTexture6 = TexturePtr(new Texture(imgBallOFF, false)); ballTexture5 = TexturePtr(new Texture(imgBallOFF, false)); ballTexture4 = TexturePtr(new Texture(imgBallOFF, false)); ballTexture3 = TexturePtr(new Texture(imgBallOFF, false)); ballTexture2 = TexturePtr(new Texture(imgBallOFF, false)); ballTexture1 = TexturePtr(new Texture(imgBallUSE, false)); } else if (ball_counts == 1) { ballTexture6 = TexturePtr(new Texture(imgBallOFF, false)); ballTexture5 = TexturePtr(new Texture(imgBallOFF, false)); ballTexture4 = TexturePtr(new Texture(imgBallOFF, false)); ballTexture3 = TexturePtr(new Texture(imgBallOFF, false)); ballTexture2 = TexturePtr(new Texture(imgBallOFF, false)); ballTexture1 = TexturePtr(new Texture(imgBallOFF, false)); } Rect skullRect = Rect(backgroundRect.x() - countPos, backgroundRect.y() - 25, ballTexture1->getSize()); Rect skullRect2 = Rect(backgroundRect.x() - countPos2, backgroundRect.y() - 25, ballTexture1->getSize()); Rect skullRect3 = Rect(backgroundRect.x() - countPos3, backgroundRect.y() - 25, ballTexture1->getSize()); Rect skullRect4 = Rect(backgroundRect.x() - countPos4, backgroundRect.y() - 25, ballTexture1->getSize()); Rect skullRect5 = Rect(backgroundRect.x() - countPos5, backgroundRect.y() - 25, ballTexture1->getSize()); Rect skullRect6 = Rect(backgroundRect.x() - countPos6, backgroundRect.y() - 25, ballTexture1->getSize()); g_painter->setOpacity(0.8f); g_painter->drawTexturedRect(skullRect, ballTexture1); g_painter->drawTexturedRect(skullRect2, ballTexture2); g_painter->drawTexturedRect(skullRect3, ballTexture3); g_painter->drawTexturedRect(skullRect4, ballTexture4); g_painter->drawTexturedRect(skullRect5, ballTexture5); g_painter->drawTexturedRect(skullRect6, ballTexture6); } /*for (int i = 0; i < duel_mode; i++) { int count = 23 - (10 * i); TexturePtr ballTexture = TexturePtr(new Texture(imgBall, false)); if(i == 4) ballTexture = TexturePtr(new Texture(imgBallUSE, false)); else if(i == 5) ballTexture = TexturePtr(new Texture(imgBallOFF, false)); Rect skullRect = Rect(backgroundRect.x() - count, backgroundRect.y() - 25, ballTexture->getSize()); g_painter->setOpacity(0.8f); g_painter->drawTexturedRect(skullRect, ballTexture); } */ g_painter->setOpacity(1.0f); } 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); } if(m_icon != Otc::NpcIconNone && m_iconTexture) { g_painter->setColor(Color::white); Rect iconRect = Rect(backgroundRect.x() + 13.5 + 12, backgroundRect.y() + 5, m_iconTexture->getSize()); g_painter->drawTexturedRect(iconRect, m_iconTexture); } } 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; if(m_walkFinishAnimEvent) { m_walkFinishAnimEvent->cancel(); m_walkFinishAnimEvent = nullptr; } // 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; // stops the walk right away terminateWalk(); } void Creature::jump(int height, int duration) { if(!m_jumpOffset.isNull()) return; m_jumpTimer.restart(); m_jumpHeight = height; m_jumpDuration = duration; updateJump(); } void Creature::updateJump() { int t = m_jumpTimer.ticksElapsed(); double a = -4 * m_jumpHeight / (m_jumpDuration * m_jumpDuration); double b = +4 * m_jumpHeight / (m_jumpDuration); double height = a*t*t + b*t; int roundHeight = stdext::round(height); int halfJumpDuration = m_jumpDuration / 2; // schedules next update if(m_jumpTimer.ticksElapsed() < m_jumpDuration) { m_jumpOffset = PointF(height, height); int diff = 0; if(m_jumpTimer.ticksElapsed() < halfJumpDuration) diff = 1; else if(m_jumpTimer.ticksElapsed() > halfJumpDuration) diff = -1; int nextT, i = 1; do { nextT = stdext::round((-b + std::sqrt(std::max<int>(b*b + 4*a*(roundHeight+diff*i), 0.0)) * diff) / (2*a)); ++i; if(nextT < halfJumpDuration) diff = 1; else if(nextT > halfJumpDuration) diff = -1; } while(nextT - m_jumpTimer.ticksElapsed() == 0 && i < 3); auto self = static_self_cast<Creature>(); g_dispatcher.scheduleEvent([self] { self->updateJump(); }, nextT - m_jumpTimer.ticksElapsed()); } else m_jumpOffset = PointF(0, 0); } 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::onDeath() { callLuaField("onDeath"); } void Creature::updateWalkAnimation(int totalPixelsWalked) { // update outfit animation if(m_outfit.getCategory() != ThingCategoryCreature) return; int footAnimPhases = getAnimationPhases() - 1; int footDelay = getStepDuration(true) / 3; // Since mount is a different outfit we need to get the mount animation phases if(m_outfit.getMount() != 0) { ThingType *type = g_things.rawGetThingType(m_outfit.getMount(), m_outfit.getCategory()); footAnimPhases = type->getAnimationPhases() - 1; } if(footAnimPhases == 0) m_walkAnimationPhase = 0; else if(m_footStepDrawn && m_footTimer.ticksElapsed() >= footDelay && totalPixelsWalked < 32) { m_footStep++; m_walkAnimationPhase = 1 + (m_footStep % footAnimPhases); m_footStepDrawn = false; m_footTimer.restart(); } else if(m_walkAnimationPhase == 0 && totalPixelsWalked < 32) { m_walkAnimationPhase = 1 + (m_footStep % footAnimPhases); } if(totalPixelsWalked == 32 && !m_walkFinishAnimEvent) { auto self = static_self_cast<Creature>(); m_walkFinishAnimEvent = g_dispatcher.scheduleEvent([self] { if(!self->m_walking || self->m_walkTimer.ticksElapsed() >= self->getStepDuration(true)) self->m_walkAnimationPhase = 0; self->m_walkFinishAnimEvent = nullptr; }, std::min<int>(footDelay, 200)); } } 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.notificateTileUpdate(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<int>(m_walkTimer.ticksElapsed() / walkTicksPerPixel, 32.0f); // needed for paralyze effect m_walkedPixels = std::max<int>(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; // reset walk animation states m_walkOffset = Point(0,0); m_walkAnimationPhase = 0; } void Creature::setName(const std::string& name) { m_nameCache.setText(name); m_name = name; } void Creature::setHealthPercent(uint8 healthPercent) { if(healthPercent > 92) m_informationColor = Color(0x00, 0xBC, 0x00); else if(healthPercent > 60) m_informationColor = Color(0x50, 0xA1, 0x50); else if(healthPercent > 30) m_informationColor = Color(0xA1, 0xA1, 0x00); else if(healthPercent > ? m_informationColor = Color(0xBF, 0x0A, 0x0A); else if(healthPercent > 3) m_informationColor = Color(0x91, 0x0F, 0x0F); else m_informationColor = Color(0x85, 0x0C, 0x0C); m_healthPercent = healthPercent; callLuaField("onHealthPercentChange", healthPercent); if(healthPercent <= 0) onDeath(); } void Creature::setDirection(Otc::Direction direction) { assert(direction != Otc::InvalidDirection); m_direction = direction; } void Creature::setOutfit(const Outfit& outfit) { Outfit oldOutfit = m_outfit; if(outfit.getCategory() != ThingCategoryCreature) { if(!g_things.isValidDatId(outfit.getAuxId(), outfit.getCategory())) return; m_outfit.setAuxId(outfit.getAuxId()); m_outfit.setCategory(outfit.getCategory()); m_outfit2.setAuxId(outfit.getAuxId()); m_outfit2.setCategory(outfit.getCategory()); } else { if(outfit.getId() > 0 && !g_things.isValidDatId(outfit.getId(), ThingCategoryCreature)) return; m_outfit = outfit; m_outfit2 = outfit; } m_walkAnimationPhase = 0; // might happen when player is walking and outfit is changed. callLuaField("onOutfitChange", m_outfit, oldOutfit); } void Creature::setOutfitColor(const Color& color, int duration) { if(m_outfitColorUpdateEvent) { m_outfitColorUpdateEvent->cancel(); m_outfitColorUpdateEvent = nullptr; } if(duration > 0) { Color delta = (color - m_outfitColor) / (float)duration; m_outfitColorTimer.restart(); updateOutfitColor(m_outfitColor, color, delta, duration); } else m_outfitColor = color; } void Creature::updateOutfitColor(Color color, Color finalColor, Color delta, int duration) { if(m_outfitColorTimer.ticksElapsed() < duration) { m_outfitColor = color + delta * m_outfitColorTimer.ticksElapsed(); auto self = static_self_cast<Creature>(); m_outfitColorUpdateEvent = g_dispatcher.scheduleEvent([=] { self->updateOutfitColor(color, finalColor, delta, duration); }, 100); } else { m_outfitColor = finalColor; } } 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::setBaseSpeed(double baseSpeed) { if(m_baseSpeed != baseSpeed) { double oldBaseSpeed = m_baseSpeed; m_baseSpeed = baseSpeed; callLuaField("onBaseSpeedChange", baseSpeed, oldBaseSpeed); } } 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::setIcon(uint8 icon) { m_icon = icon; callLuaField("onIconChange", m_icon); } 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::setIconTexture(const std::string& filename) { m_iconTexture = 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, Otc::Direction dir) { int speed = m_speed; if(speed < 1) return 0; if(g_game.getFeature(Otc::GameNewSpeedLaw)) speed *= 2; int groundSpeed = 0; Position tilePos; if(dir == Otc::InvalidDirection) tilePos = m_lastStepToPosition; else tilePos = m_position.translatedToDirection(dir); 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<int>(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.getClientVersion() >= 900) interval = (interval / g_game.getServerBeat()) * g_game.getServerBeat(); float factor = 3; if(g_game.getClientVersion() <= 810) factor = 2; interval = std::max<int>(interval, g_game.getServerBeat()); if(!ignoreDiagonal && (m_lastStepDirection == Otc::NorthWest || m_lastStepDirection == Otc::NorthEast || m_lastStepDirection == Otc::SouthWest || m_lastStepDirection == Otc::SouthEast)) interval *= factor; 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; if(m_outfit.getMount() != 0) { auto datType = g_things.rawGetThingType(m_outfit.getMount(), ThingCategoryCreature); return datType->getDisplacementX(); } return Thing::getDisplacementX(); } int Creature::getDisplacementY() { if(m_outfit.getCategory() == ThingCategoryEffect) return 8; else if(m_outfit.getCategory() == ThingCategoryItem) return 0; if(m_outfit.getMount() != 0) { auto datType = g_things.rawGetThingType(m_outfit.getMount(), ThingCategoryCreature); return datType->getDisplacementY(); } 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<int>(exactSize, Thing::getExactSize(layer, xPattern, yPattern, zPattern, animationPhase)); } return exactSize; } const ThingTypePtr& Creature::getThingType() { return g_things.getThingType(m_outfit.getId(), ThingCategoryCreature); } const ThingTypePtr& Creature::getThingType2() { return g_things.getThingType2(m_outfit.getId(), ThingCategoryCreature); } ThingType* Creature::rawGetThingType() { if (!iniciou) { novaOutType = g_things.getThingTypeInSecondList(m_outfit2.getId(), ThingCategoryCreature); iniciou = true; } return g_things.rawGetThingType(m_outfit.getId(), ThingCategoryCreature); } ThingType* Creature::rawGetThingType2() { if (!iniciou) { novaOutType = g_things.getThingTypeInSecondList(m_outfit2.getId(), ThingCategoryCreature); iniciou = true; } return novaOutType; } a linha: g_painter->drawTexturedRect(rect, effect->getThingType()->getTextureEX(0)); Link para o comentário Compartilhar em outros sites More sharing options...
Wickass 10 Postado Agosto 15, 2018 Share Postado Agosto 15, 2018 Em 26/07/2018 em 22:48, Refe disse: quais ? a linha: g_painter->drawTexturedRect(rect, effect->getThingType()->getTextureEX(0)); Pode mandar a png dnv ? nao esta carregando a que esta no topico agradeço Link para o comentário Compartilhar em outros sites More sharing options...
TheFlacks 5 Postado Setembro 23, 2018 Share Postado Setembro 23, 2018 Manda a imagem da target do pxg dnv Link para o comentário Compartilhar em outros sites More sharing options...
Davy Returns 0 Postado Setembro 24, 2018 Share Postado Setembro 24, 2018 manda target dnv Link para o comentário Compartilhar em outros sites More sharing options...
TheFlacks 5 Postado Setembro 24, 2018 Share Postado Setembro 24, 2018 #MandaATarget Link para o comentário Compartilhar em outros sites More sharing options...
Visitante Postado Setembro 25, 2018 Share Postado Setembro 25, 2018 Atualizando tópico com o target. Link para o comentário Compartilhar em outros sites More sharing options...
Posts Recomendados