void Monster::getPathSearchParams(const Creature* creature, FindPathParams& fpp) const { Creature::getPathSearchParams(creature, fpp); fpp.minTargetDist = 1; fpp.maxTargetDist = mType->targetDistance; if(isSummon()) { if(master == creature) { fpp.maxTargetDist = 2; fpp.fullPathSearch = true; } else if(mType->targetDistance <= 1) fpp.fullPathSearch = true; else fpp.fullPathSearch = !canUseAttack(getPosition(), creature); } else if(isFleeing()) { //Distance should be higher than the client view range (Map::maxClientViewportX/Map::maxClientViewportY) fpp.maxTargetDist = Map::maxViewportX; fpp.clearSight = fpp.fullPathSearch = false; fpp.keepDistance = true; } else if(mType->targetDistance <= 1) fpp.fullPathSearch = true; else fpp.fullPathSearch = !canUseAttack(getPosition(), creature); }
void Monster::onThink(uint32_t interval) { Creature::onThink(interval); if(despawn()) { g_game.internalTeleport(this, masterPos); setIdle(true); } else { updateIdleStatus(); if(!isIdle) { addEventWalk(); if(isSummon()) { if(!attackedCreature) { if(getMaster() && getMaster()->getAttackedCreature()) { ///This happens if the monster is summoned during combat selectTarget(getMaster()->getAttackedCreature()); } else if(getMaster() != followCreature) { //Our master has not ordered us to attack anything, lets follow him around instead. setFollowCreature(getMaster()); } } else if(attackedCreature == this) setFollowCreature(NULL); else if(followCreature != attackedCreature) { //This happens just after a master orders an attack, so lets follow it aswell. setFollowCreature(attackedCreature); } } else if(!targetList.empty()) { if(!followCreature || !hasFollowPath) searchTarget(); else if(isFleeing()) { if(attackedCreature && !canUseAttack(getPosition(), attackedCreature)) searchTarget(TARGETSEARCH_ATTACKRANGE); } } onThinkTarget(interval); onThinkYell(interval); onThinkDefense(interval); } } }
void Monster::onThink(uint32_t interval) { Creature::onThink(interval); if(despawn()) { g_game.removeCreature(this, true); setIdle(true); return; } updateIdleStatus(); if(isIdle) return; if(teleportToMaster && doTeleportToMaster()) teleportToMaster = false; addEventWalk(); if(getMaster()){ if(getPosition().z != getMaster()->getPosition().z){ g_game.internalTeleport(this, getMaster()->getPosition(), false); //g_game.addMagicEffect(getPosition(), MAGIC_EFFECT_SOUND_YELLOW); } } if(isSummon()) { if(!attackedCreature) { std::string strValue; if(getMaster() && getMaster()->getAttackedCreature()) //This happens if the monster is summoned during combat selectTarget(getMaster()->getAttackedCreature()); else{ setFollowCreature((getMaster()->getStorage(500, strValue) && strValue != "-1") ? NULL : getMaster()); } } else if(attackedCreature == this) setFollowCreature(NULL); else if(followCreature != attackedCreature) //This happens just after a master orders an attack, so lets follow it aswell. setFollowCreature(attackedCreature); } else if(!targetList.empty()) { if(!followCreature || !hasFollowPath) searchTarget(); else if(isFleeing() && attackedCreature && !canUseAttack(getPosition(), attackedCreature)) searchTarget(TARGETSEARCH_ATTACKRANGE); } onThinkTarget(interval); onThinkYell(interval); onThinkDefense(interval); }
void Actor::getPathSearchParams(const Creature* creature, FindPathParams& fpp) const { Creature::getPathSearchParams(creature, fpp); fpp.minTargetDist = 1; fpp.maxTargetDist = cType.targetDistance(); if(isSummon()){ if(getMaster() == creature){ fpp.maxTargetDist = 2; fpp.fullPathSearch = true; } else{ if(cType.targetDistance() <= 1){ fpp.fullPathSearch = true; } else{ fpp.fullPathSearch = !canUseAttack(getPosition(), creature); } } } else{ if(isFleeing()){ //Distance should be higher than the client view range (Map_maxClientViewportX/Map_maxClientViewportY) fpp.maxTargetDist = Map_maxViewportX; fpp.clearSight = false; fpp.keepDistance = true; fpp.fullPathSearch = false; } else{ if(cType.targetDistance() <= 1){ fpp.fullPathSearch = true; } else{ fpp.fullPathSearch = !canUseAttack(getPosition(), creature); } } } }
void Monster::getPathSearchParams(const Creature* creature, FindPathParams& fpp) const { Creature::getPathSearchParams(creature, fpp); fpp.clearSight = false; fpp.minTargetDist = 1; fpp.maxTargetDist = mType->targetDistance; //aqui std::string strValue; int32_t value; if(getStorage(502, strValue)) { value = atoi(strValue.c_str()); fpp.maxTargetDist = value; } if(isSummon()) { if(getMaster() == creature) { fpp.maxTargetDist = 2; fpp.fullPathSearch = true; } else if(mType->targetDistance <= 1) fpp.fullPathSearch = true; else fpp.fullPathSearch = !canUseAttack(getPosition(), creature); } else if(isFleeing()) { //Distance should be higher than the client view range (Map::maxClientViewportX/Map::maxClientViewportY) fpp.maxTargetDist = Map::maxViewportX; fpp.fullPathSearch = false; fpp.keepDistance = true; } else if(mType->targetDistance <= 1) fpp.fullPathSearch = true; else fpp.fullPathSearch = !canUseAttack(getPosition(), creature); }
bool Actor::searchTarget(TargetSearchType_t searchType /*= TARGETSEARCH_DEFAULT*/) { #ifdef __DEBUG__ std::cout << "Searching target... " << std::endl; #endif std::list<Creature*> resultList; const Position& myPos = getPosition(); for(CreatureList::iterator it = targetList.begin(); it != targetList.end(); ++it){ if(followCreature != (*it) && isTarget(*it)){ if(searchType == TARGETSEARCH_RANDOM || canUseAttack(myPos, *it)){ resultList.push_back(*it); } } } if(!resultList.empty()){ uint32_t index = random_range(0, resultList.size() - 1); CreatureList::iterator it = resultList.begin(); std::advance(it, index); #ifdef __DEBUG__ std::cout << "Selecting target " << (*it)->getName() << std::endl; #endif return selectTarget(*it); } if(searchType == TARGETSEARCH_ATTACKRANGE){ return false; } //lets just pick the first target in the list for(CreatureList::iterator it = targetList.begin(); it != targetList.end(); ++it){ if(followCreature != (*it) && selectTarget(*it)){ #ifdef __DEBUG__ std::cout << "Selecting target " << (*it)->getName() << std::endl; #endif return true; } } return false; }
bool Actor::getDanceStep(const Position& creaturePos, Direction& dir, bool keepAttack /*= true*/, bool keepDistance /*= true*/) { bool canDoAttackNow = canUseAttack(creaturePos, attackedCreature); assert(attackedCreature != NULL); const Position& centerPos = attackedCreature->getPosition(); uint32_t centerToDist = std::max(std::abs(creaturePos.x - centerPos.x), std::abs(creaturePos.y - centerPos.y)); uint32_t tmpDist; std::vector<Direction> dirList; if(!keepDistance || creaturePos.y - centerPos.y >= 0){ tmpDist = std::max(std::abs((creaturePos.x) - centerPos.x), std::abs((creaturePos.y - 1) - centerPos.y)); if(tmpDist == centerToDist && canWalkTo(creaturePos, NORTH)){ bool result = true; if(keepAttack){ result = (!canDoAttackNow || canUseAttack(Position(creaturePos.x, creaturePos.y - 1, creaturePos.z), attackedCreature)); } if(result){ dirList.push_back(NORTH); } } } if(!keepDistance || creaturePos.y - centerPos.y <= 0){ tmpDist = std::max(std::abs((creaturePos.x) - centerPos.x), std::abs((creaturePos.y + 1) - centerPos.y)); if(tmpDist == centerToDist && canWalkTo(creaturePos, SOUTH)){ bool result = true; if(keepAttack){ result = (!canDoAttackNow || canUseAttack(Position(creaturePos.x, creaturePos.y + 1, creaturePos.z), attackedCreature)); } if(result){ dirList.push_back(SOUTH); } } } if(!keepDistance || creaturePos.x - centerPos.x >= 0){ tmpDist = std::max(std::abs((creaturePos.x + 1) - centerPos.x), std::abs((creaturePos.y) - centerPos.y)); if(tmpDist == centerToDist && canWalkTo(creaturePos, EAST)){ bool result = true; if(keepAttack){ result = (!canDoAttackNow || canUseAttack(Position(creaturePos.x + 1, creaturePos.y, creaturePos.z), attackedCreature)); } if(result){ dirList.push_back(EAST); } } } if(!keepDistance || creaturePos.x - centerPos.x <= 0){ tmpDist = std::max(std::abs((creaturePos.x - 1) - centerPos.x), std::abs((creaturePos.y) - centerPos.y)); if(tmpDist == centerToDist && canWalkTo(creaturePos, WEST)){ bool result = true; if(keepAttack){ result = (!canDoAttackNow || canUseAttack(Position(creaturePos.x - 1, creaturePos.y, creaturePos.z), attackedCreature)); } if(result){ dirList.push_back(WEST); } } } if(!dirList.empty()){ std::random_shuffle(dirList.begin(), dirList.end()); dir = dirList[random_range(0, dirList.size() - 1)]; return true; } return false; }
bool Monster::searchTarget(TargetSearchType_t searchType /*= TARGETSEARCH_DEFAULT*/) { #ifdef __DEBUG__ std::clog << "Searching target... " << std::endl; #endif std::list<Creature*> resultList; const Position& myPos = getPosition(); for(CreatureList::iterator it = targetList.begin(); it != targetList.end(); ++it) { if(followCreature != (*it) && isTarget(*it) && (searchType == TARGETSEARCH_RANDOM || canUseAttack(myPos, *it))) resultList.push_back(*it); } switch(searchType) { case TARGETSEARCH_NEAREST: { Creature* target = NULL; int32_t range = -1; for(CreatureList::iterator it = resultList.begin(); it != resultList.end(); ++it) { int32_t tmp = std::max(std::abs(myPos.x - (*it)->getPosition().x), std::abs(myPos.y - (*it)->getPosition().y)); if(range >= 0 && tmp >= range) continue; target = *it; range = tmp; } if(target && selectTarget(target)) return target; break; } default: { if(!resultList.empty()) { CreatureList::iterator it = resultList.begin(); std::advance(it, random_range(0, resultList.size() - 1)); #ifdef __DEBUG__ std::clog << "Selecting target " << (*it)->getName() << std::endl; #endif return selectTarget(*it); } if(searchType == TARGETSEARCH_ATTACKRANGE) return false; break; } } //lets just pick the first target in the list for(CreatureList::iterator it = targetList.begin(); it != targetList.end(); ++it) { if(followCreature == (*it) || !selectTarget(*it)) continue; #ifdef __DEBUG__ std::clog << "Selecting target " << (*it)->getName() << std::endl; #endif return true; } return false; }
bool Monster::searchTarget(TargetSearchType_t searchType /*= TARGETSEARCH_DEFAULT*/) { #ifdef __DEBUG__ std::cout << "Searching target... " << std::endl; #endif std::list<Creature*> resultList; const Position& myPos = getPosition(); for(CreatureList::iterator it = targetList.begin(); it != targetList.end(); ++it) { if(followCreature != (*it) && isTarget(*it)) { if(searchType == TARGETSEARCH_RANDOM || canUseAttack(myPos, *it)) resultList.push_back(*it); } } switch(searchType) { case TARGETSEARCH_NEAREAST: { Creature* target = NULL; int32_t minRange = -1; for(std::list<Creature*>::iterator it = resultList.begin(); it != resultList.end(); ++it) { const Position& pos = (*it)->getPosition(); if(minRange == -1 || std::max(std::abs(myPos.x - pos.x), std::abs(myPos.y - pos.y)) < minRange) { target = *it; minRange = std::max(std::abs(myPos.x - pos.x), std::abs(myPos.y - pos.y)); } } if(target && selectTarget(target)) return true; break; } case TARGETSEARCH_DEFAULT: case TARGETSEARCH_ATTACKRANGE: case TARGETSEARCH_RANDOM: default: { if(!resultList.empty()) { uint32_t index = random_range(0, resultList.size() - 1); CreatureList::iterator it = resultList.begin(); std::advance(it, index); #ifdef __DEBUG__ std::cout << "Selecting target " << (*it)->getName() << std::endl; #endif return selectTarget(*it); } if(searchType == TARGETSEARCH_ATTACKRANGE) return false; break; } } //lets just pick the first target in the list for(CreatureList::iterator it = targetList.begin(); it != targetList.end(); ++it) { if(followCreature != (*it) && selectTarget(*it)) { #ifdef __DEBUG__ std::cout << "Selecting target " << (*it)->getName() << std::endl; #endif return true; } } return false; }
void Monster::onThink(uint32_t interval) { Creature::onThink(interval); if (mType->info.thinkEvent != -1) { // onThink(self, interval) LuaScriptInterface* scriptInterface = mType->info.scriptInterface; if (!scriptInterface->reserveScriptEnv()) { std::cout << "[Error - Monster::onThink] Call stack overflow" << std::endl; return; } ScriptEnvironment* env = scriptInterface->getScriptEnv(); env->setScriptId(mType->info.thinkEvent, scriptInterface); lua_State* L = scriptInterface->getLuaState(); scriptInterface->pushFunction(mType->info.thinkEvent); LuaScriptInterface::pushUserdata<Monster>(L, this); LuaScriptInterface::setMetatable(L, -1, "Monster"); lua_pushnumber(L, interval); if (scriptInterface->callFunction(2)) { return; } } if (!isInSpawnRange(position)) { g_game.internalTeleport(this, masterPos); setIdle(true); } else { updateIdleStatus(); if (!isIdle) { addEventWalk(); if (isSummon()) { if (!attackedCreature) { if (getMaster() && getMaster()->getAttackedCreature()) { //This happens if the monster is summoned during combat selectTarget(getMaster()->getAttackedCreature()); } else if (getMaster() != followCreature) { //Our master has not ordered us to attack anything, lets follow him around instead. setFollowCreature(getMaster()); } } else if (attackedCreature == this) { setFollowCreature(nullptr); } else if (followCreature != attackedCreature) { //This happens just after a master orders an attack, so lets follow it aswell. setFollowCreature(attackedCreature); } } else if (!targetList.empty()) { if (!followCreature || !hasFollowPath) { searchTarget(); } else if (isFleeing()) { if (attackedCreature && !canUseAttack(getPosition(), attackedCreature)) { searchTarget(TARGETSEARCH_ATTACKRANGE); } } } onThinkTarget(interval); onThinkYell(interval); onThinkDefense(interval); } } }
bool Monster::searchTarget(TargetSearchType_t searchType /*= TARGETSEARCH_DEFAULT*/) { std::list<Creature*> resultList; const Position& myPos = getPosition(); for (Creature* creature : targetList) { if (followCreature != creature && isTarget(creature)) { if (searchType == TARGETSEARCH_RANDOM || canUseAttack(myPos, creature)) { resultList.push_back(creature); } } } switch (searchType) { case TARGETSEARCH_NEAREST: { Creature* target = nullptr; if (!resultList.empty()) { auto it = resultList.begin(); target = *it; if (++it != resultList.end()) { const Position& targetPosition = target->getPosition(); int32_t minRange = Position::getDistanceX(myPos, targetPosition) + Position::getDistanceY(myPos, targetPosition); do { const Position& pos = (*it)->getPosition(); int32_t distance = Position::getDistanceX(myPos, pos) + Position::getDistanceY(myPos, pos); if (distance < minRange) { target = *it; minRange = distance; } } while (++it != resultList.end()); } } else { int32_t minRange = std::numeric_limits<int32_t>::max(); for (Creature* creature : targetList) { if (!isTarget(creature)) { continue; } const Position& pos = creature->getPosition(); int32_t distance = Position::getDistanceX(myPos, pos) + Position::getDistanceY(myPos, pos); if (distance < minRange) { target = creature; minRange = distance; } } } if (target && selectTarget(target)) { return true; } break; } case TARGETSEARCH_DEFAULT: case TARGETSEARCH_ATTACKRANGE: case TARGETSEARCH_RANDOM: default: { if (!resultList.empty()) { auto it = resultList.begin(); std::advance(it, uniform_random(0, resultList.size() - 1)); return selectTarget(*it); } if (searchType == TARGETSEARCH_ATTACKRANGE) { return false; } break; } } //lets just pick the first target in the list for (Creature* target : targetList) { if (followCreature != target && selectTarget(target)) { return true; } } return false; }
bool Monster::getDanceStep(const Position& creaturePos, Direction& direction, bool keepAttack /*= true*/, bool keepDistance /*= true*/) { bool canDoAttackNow = canUseAttack(creaturePos, attackedCreature); assert(attackedCreature != nullptr); const Position& centerPos = attackedCreature->getPosition(); int_fast32_t offset_x = Position::getOffsetX(creaturePos, centerPos); int_fast32_t offset_y = Position::getOffsetY(creaturePos, centerPos); int_fast32_t distance_x = std::abs(offset_x); int_fast32_t distance_y = std::abs(offset_y); uint32_t centerToDist = std::max<uint32_t>(distance_x, distance_y); std::vector<Direction> dirList; if (!keepDistance || offset_y >= 0) { uint32_t tmpDist = std::max<uint32_t>(distance_x, std::abs((creaturePos.getY() - 1) - centerPos.getY())); if (tmpDist == centerToDist && canWalkTo(creaturePos, DIRECTION_NORTH)) { bool result = true; if (keepAttack) { result = (!canDoAttackNow || canUseAttack(Position(creaturePos.x, creaturePos.y - 1, creaturePos.z), attackedCreature)); } if (result) { dirList.push_back(DIRECTION_NORTH); } } } if (!keepDistance || offset_y <= 0) { uint32_t tmpDist = std::max<uint32_t>(distance_x, std::abs((creaturePos.getY() + 1) - centerPos.getY())); if (tmpDist == centerToDist && canWalkTo(creaturePos, DIRECTION_SOUTH)) { bool result = true; if (keepAttack) { result = (!canDoAttackNow || canUseAttack(Position(creaturePos.x, creaturePos.y + 1, creaturePos.z), attackedCreature)); } if (result) { dirList.push_back(DIRECTION_SOUTH); } } } if (!keepDistance || offset_x <= 0) { uint32_t tmpDist = std::max<uint32_t>(std::abs((creaturePos.getX() + 1) - centerPos.getX()), distance_y); if (tmpDist == centerToDist && canWalkTo(creaturePos, DIRECTION_EAST)) { bool result = true; if (keepAttack) { result = (!canDoAttackNow || canUseAttack(Position(creaturePos.x + 1, creaturePos.y, creaturePos.z), attackedCreature)); } if (result) { dirList.push_back(DIRECTION_EAST); } } } if (!keepDistance || offset_x >= 0) { uint32_t tmpDist = std::max<uint32_t>(std::abs((creaturePos.getX() - 1) - centerPos.getX()), distance_y); if (tmpDist == centerToDist && canWalkTo(creaturePos, DIRECTION_WEST)) { bool result = true; if (keepAttack) { result = (!canDoAttackNow || canUseAttack(Position(creaturePos.x - 1, creaturePos.y, creaturePos.z), attackedCreature)); } if (result) { dirList.push_back(DIRECTION_WEST); } } } if (!dirList.empty()) { std::shuffle(dirList.begin(), dirList.end(), getRandomGenerator()); direction = dirList[uniform_random(0, dirList.size() - 1)]; return true; } return false; }
Direction Monster::getDanceStep(bool keepAttack /*= true*/, bool keepDistance /*= true*/) const { Position position = getPosition(); assert(attackedCreature); bool canDoAttackNow = canUseAttack(position, attackedCreature); const Position& centerPos = attackedCreature->getPosition(); uint32_t tmpDist, centerToDist = std::max(std::abs(static_cast<signed>(position.x) - static_cast<signed>(centerPos.x)), std::abs(static_cast<signed>(position.y) - static_cast<signed>(centerPos.y))); if (centerToDist == 0) { return getRandomStepDirection(false); } std::vector<Direction> dirVector; if(!keepDistance || position.y >= centerPos.y) { tmpDist = std::max(std::abs(static_cast<signed>(position.x) - static_cast<signed>(centerPos.x)), std::abs(static_cast<signed>(position.y - 1) - static_cast<signed>(centerPos.y))); if(tmpDist == centerToDist && canMoveTo(Direction::NORTH)) { bool result = true; if(keepAttack) result = (!canDoAttackNow || canUseAttack(Position(position.x, position.y - 1, position.z), attackedCreature)); if(result) dirVector.push_back(Direction::NORTH); } } if(!keepDistance || position.y <= centerPos.y) { tmpDist = std::max(std::abs(static_cast<signed>(position.x) - static_cast<signed>(centerPos.x)), std::abs(static_cast<signed>(position.y + 1) - static_cast<signed>(centerPos.y))); if(tmpDist == centerToDist && canMoveTo(Direction::SOUTH)) { bool result = true; if(keepAttack) result = (!canDoAttackNow || canUseAttack(Position(position.x, position.y + 1, position.z), attackedCreature)); if(result) dirVector.push_back(Direction::SOUTH); } } if(!keepDistance || position.x <= centerPos.x) { tmpDist = std::max(std::abs(static_cast<signed>(position.x + 1) - static_cast<signed>(centerPos.x)), std::abs(static_cast<signed>(position.y) - static_cast<signed>(centerPos.y))); if(tmpDist == centerToDist && canMoveTo(Direction::EAST)) { bool result = true; if(keepAttack) result = (!canDoAttackNow || canUseAttack(Position(position.x + 1, position.y, position.z), attackedCreature)); if(result) dirVector.push_back(Direction::EAST); } } if(!keepDistance || position.x >= centerPos.x) { tmpDist = std::max(std::abs(static_cast<signed>(position.x - 1) - static_cast<signed>(centerPos.x)), std::abs(static_cast<signed>(position.y) - static_cast<signed>(centerPos.y))); if(tmpDist == centerToDist && canMoveTo(Direction::WEST)) { bool result = true; if(keepAttack) result = (!canDoAttackNow || canUseAttack(Position(position.x - 1, position.y, position.z), attackedCreature)); if(result) dirVector.push_back(Direction::WEST); } } if(dirVector.empty()) return Direction::NONE; return dirVector[random_range<uint32_t>(0, dirVector.size() - 1)]; }