Ejemplo n.º 1
0
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);
}
Ejemplo n.º 2
0
bool Monster::canUseSpell(const Position& pos, const Position& targetPos,
                          const spellBlock_t& sb, uint32_t interval, bool& inRange, bool& resetTicks)
{
	inRange = true;

	if (sb.isMelee && isFleeing()) {
		return false;
	}

	if (extraMeleeAttack) {
		lastMeleeAttack = OTSYS_TIME();
	} else if (sb.isMelee && (OTSYS_TIME() - lastMeleeAttack) < 1500) {
		return false;
	}

	if (!sb.isMelee || !extraMeleeAttack) {
		if (sb.speed > attackTicks) {
			resetTicks = false;
			return false;
		}

		if (attackTicks % sb.speed >= interval) {
			//already used this spell for this round
			return false;
		}
	}

	if (sb.range != 0 && std::max<uint32_t>(Position::getDistanceX(pos, targetPos), Position::getDistanceY(pos, targetPos)) > sb.range) {
		inRange = false;
		return false;
	}
	return true;
}
Ejemplo n.º 3
0
Direction Monster::getWanderingDirection() const {
	if (!isAlive()) {
		return Direction::NONE;
	}

	Direction direction = Direction::NONE;
	if (attackedCreature != nullptr) {
		//target dancing
		if(isFleeing())
			direction = getDanceStep(false, false);
		else if(_type->staticAttackChance < (uint32_t)random_range(1, 100))
			direction = getDanceStep();
	}
	else {
		direction = getRandomStepDirection();
	}

	if(direction != Direction::NONE && (canPushItems() || canPushCreatures()))
	{
		if(Tile* tile = server.game().getTile(Spells::getCasterPosition(this, direction)))
		{
			// TODO refactor!

			if(canPushItems())
				const_cast<Monster*>(this)->pushItems(tile);
		}
	}

	return direction;
}
Ejemplo n.º 4
0
void Monster::doAttacking(uint32_t interval)
{
	if(!attackedCreature || (isSummon() && attackedCreature == this))
		return;

	bool updateLook = true, outOfRange = true;
	resetTicks = interval;
	attackTicks += interval;

	const Position& myPos = getPosition();
	const Position& targetPos = attackedCreature->getPosition();
	for(SpellList::iterator it = mType->spellAttackList.begin(); it != mType->spellAttackList.end(); ++it)
	{
		if(it->isMelee && isFleeing())
			continue;

		bool inRange = false;
		if(canUseSpell(myPos, targetPos, *it, interval, inRange))
		{
			if(it->chance >= (uint32_t)random_range(1, 100))
			{
				if(updateLook)
				{
					updateLookDirection();
					updateLook = false;
				}

				double multiplier;
				if(maxCombatValue > 0) //defense
					multiplier = g_config.getDouble(ConfigManager::RATE_MONSTER_DEFENSE);
				else //attack
					multiplier = g_config.getDouble(ConfigManager::RATE_MONSTER_ATTACK);

				minCombatValue = (int32_t)(it->minCombatValue * multiplier);
				maxCombatValue = (int32_t)(it->maxCombatValue * multiplier);

				it->spell->castSpell(this, attackedCreature);
				if(it->isMelee)
					extraMeleeAttack = false;
#ifdef __DEBUG__
				static uint64_t prevTicks = OTSYS_TIME();
				std::clog << "doAttacking ticks: " << OTSYS_TIME() - prevTicks << std::endl;
				prevTicks = OTSYS_TIME();
#endif
			}
		}

		if(inRange)
			outOfRange = false;
		else if(it->isMelee) //melee swing out of reach
			extraMeleeAttack = true;
	}

	if(updateLook)
		updateLookDirection();

	if(resetTicks)
		attackTicks = 0;
}
Ejemplo n.º 5
0
bool Actor::getNextStep(Direction& dir, uint32_t& flags)
{
  if(isIdle || getHealth() <= 0){
    //we dont have anyone watching might aswell stop walking
    eventWalk = 0;
    return false;
  }

  bool result = false;
  if((!followCreature || !hasFollowPath) && !isSummon()){
    if(followCreature){
      result = getRandomStep(getPosition(), dir);
    }else{
      if(getTimeSinceLastMove() > 1000){
        //choose a random direction
        result = getRandomStep(getPosition(), dir);
      }
    }
  }
  else if(isSummon() || followCreature){
    result = Creature::getNextStep(dir, flags);
    if(result){
      flags |= FLAG_PATHFINDING;
    }
    else{
      //target dancing
      if(attackedCreature && attackedCreature == followCreature){
        if(isFleeing()){
          result = getDanceStep(getPosition(), dir, false, false);
        }
        else if(cType.staticAttackChance() < (uint32_t)random_range(1, 100)){
          result = getDanceStep(getPosition(), dir);
        }
      }
    }
  }

  if(result && (canPushItems() || canPushCreatures()) ){
    const Position& pos = Combat::getCasterPosition(this, dir);
    Tile* tile = g_game.getParentTile(pos.x, pos.y, pos.z);
    if(tile){
      if(canPushItems()){
        pushItems(tile);
      }

      if(canPushCreatures()){
        pushCreatures(tile);
      }
    }
#ifdef __DEBUG__
    else{
      std::cout << "getNextStep - no tile." << std::endl;
    }
#endif
  }

  return result;
}
Ejemplo n.º 6
0
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);
		}
	}
}
Ejemplo n.º 7
0
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);
}
Ejemplo n.º 8
0
void Monster::doAttacking(uint32_t interval)
{
	if(!attackedCreature)
		return;

	bool updateLook = true;
	resetTicks = (interval != 0);
	attackTicks += interval;

	const Position& myPos = getPosition();
	for(SpellList::iterator it = _type->spellAttackList.begin(); it != _type->spellAttackList.end(); ++it)
	{
		if(!attackedCreature || !attackedCreature->isAlive())
			break;

		const Position& targetPos = attackedCreature->getPosition();
		if(it->isMelee && isFleeing())
			continue;

		bool inRange = false;
		if(canUseSpell(myPos, targetPos, *it, interval, inRange))
		{
			if(it->chance >= (uint32_t)random_range(1, 100))
			{
				if(updateLook)
				{
					updateLookDirection();
					updateLook = false;
				}

				double multiplier;
				if(maxCombatValue > 0) //defense
					multiplier = server.configManager().getDouble(ConfigManager::RATE_MONSTER_DEFENSE);
				else //attack
					multiplier = server.configManager().getDouble(ConfigManager::RATE_MONSTER_ATTACK);

				minCombatValue = (int32_t)(it->minCombatValue * multiplier);
				maxCombatValue = (int32_t)(it->maxCombatValue * multiplier);

				it->spell->castSpell(this, attackedCreature);
				if(it->isMelee)
					extraMeleeAttack = false;
			}
		}

		if(!inRange && it->isMelee) //melee swing out of reach
			extraMeleeAttack = true;
	}

	if(updateLook)
		updateLookDirection();

	if(resetTicks)
		attackTicks = 0;
}
Ejemplo n.º 9
0
bool Monster::getNextStep(Direction& dir, uint32_t& flags)
{
	if(isIdle || getHealth() <= 0)
	{
		//we dont have anyone watching might aswell stop walking
		eventWalk = 0;
		return false;
	}

	bool result = false;
	if((!followCreature || !hasFollowPath) && !isSummon())
	{
		if(followCreature || getTimeSinceLastMove() > 1000) //choose a random direction
			result = getRandomStep(getPosition(), dir);
	}
	else if(isSummon() || followCreature)
	{
		result = Creature::getNextStep(dir, flags);
		if(!result)
		{
			//target dancing
			if(attackedCreature && attackedCreature == followCreature)
			{
				if(isFleeing())
					result = getDanceStep(getPosition(), dir, false, false);
				else if(mType->staticAttackChance < (uint32_t)random_range(1, 100))
					result = getDanceStep(getPosition(), dir);
			}
		}
		else
			flags |= FLAG_PATHFINDING;
	}

	if(result && (canPushItems() || canPushCreatures()))
	{
		if(Tile* tile = g_game.getTile(Spells::getCasterPosition(this, dir)))
		{
			if(canPushItems())
				pushItems(tile);

			if(canPushCreatures())
				pushCreatures(tile);
		}
#ifdef __DEBUG__
		else
			std::clog << "[Warning - Monster::getNextStep] no tile found." << std::endl;
#endif
	}

	return result;
}
Ejemplo n.º 10
0
bool Monster::getNextStep(Direction& direction, uint32_t& flags)
{
	if (isIdle || getHealth() <= 0) {
		//we dont have anyone watching might aswell stop walking
		eventWalk = 0;
		return false;
	}

	bool result = false;
	if ((!followCreature || !hasFollowPath) && (!isSummon() || !isMasterInRange)) {
		if (followCreature || getTimeSinceLastMove() > 1000) {
			//choose a random direction
			result = getRandomStep(getPosition(), direction);
		}
	} else if ((isSummon() && isMasterInRange) || followCreature) {
		result = Creature::getNextStep(direction, flags);
		if (result) {
			flags |= FLAG_PATHFINDING;
		} else {
			//target dancing
			if (attackedCreature && attackedCreature == followCreature) {
				if (isFleeing()) {
					result = getDanceStep(getPosition(), direction, false, false);
				} else if (mType->info.staticAttackChance < static_cast<uint32_t>(uniform_random(1, 100))) {
					result = getDanceStep(getPosition(), direction);
				}
			}
		}
	}

	if (result && (canPushItems() || canPushCreatures())) {
		const Position& pos = Spells::getCasterPosition(this, direction);
		Tile* tile = g_game.map.getTile(pos);
		if (tile) {
			if (canPushItems()) {
				Monster::pushItems(tile);
			}

			if (canPushCreatures()) {
				Monster::pushCreatures(tile);
			}
		}
	}

	return result;
}
Ejemplo n.º 11
0
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);
      }
    }
  }
}
Ejemplo n.º 12
0
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);
}
Ejemplo n.º 13
0
void Monster::doAttacking(uint32_t interval)
{
	if(!attackedCreature || (isSummon() && attackedCreature == this))
		return; // aqui

    const Position& myPos = getPosition();
    const Position& targetPos = attackedCreature->getPosition();
	
    FindPathParams fpp;
    
    	fpp.fullPathSearch = true;
    	fpp.maxSearchDist = -1;
    	fpp.minTargetDist = 0;
    	fpp.maxTargetDist = 1;
    	
	    std::string valueString;
    	std::list<Direction> dirList;
    	if(attackedCreature->getPlayer()){
           if(Creature* summon = attackedCreature->pushBackSummonOne())
                  selectTarget(summon);
        }
    	
    /*	
    	if(!g_game.getPathToEx(this, targetPos, dirList, fpp) && attackedCreature->isSummon()){
            selectTarget(attackedCreature->getMaster());
            
            std::string strValue; int32_t value;
				if(getStorage(8085, strValue))
				{
				   value = atoi(strValue.c_str());
				}
				if(value == 0) 
				  g_game.addAnimatedText(getPosition(), 215, "GRRR!");
				  
            setStorage(8085, "2");
        }
            
        if(attackedCreature->getPlayer()){
           if(Creature* summon = attackedCreature->pushBackSummonOne()){
               if(g_game.getPathToEx(this, summon->getPosition(), dirList, fpp)){
                  selectTarget(summon);
                  std::string strValue, playerStor; int32_t value, value2;
    				if(getStorage(8085, strValue))
    				{
    				   value = atoi(strValue.c_str());
    				}
        				if(value == 2) 
        				   g_game.addAnimatedText(getPosition(), 215, "Hmpf");
        				   
        				  
                  setStorage(8085, "0");
               }
           }else
                  setStorage(8085, "1");
        } 
        */

	bool updateLook = true, outOfRange = true;
	resetTicks = interval;
	attackTicks += interval;

	
	for(SpellList::iterator it = mType->spellAttackList.begin(); it != mType->spellAttackList.end(); ++it)
	{
		if(it->isMelee && isFleeing())
			continue;

		bool inRange = false;
		if(canUseSpell(myPos, targetPos, *it, interval, inRange))
		{
			if(it->chance >= (uint32_t)random_range(1, 100))
			{
				if(updateLook)
				{
					updateLookDirection();
					updateLook = false;
				}

				double multiplier;
				if(maxCombatValue > 0) //defense
					multiplier = g_config.getDouble(ConfigManager::RATE_MONSTER_DEFENSE);
				else //attack
					multiplier = g_config.getDouble(ConfigManager::RATE_MONSTER_ATTACK);

				minCombatValue = (int32_t)(it->minCombatValue * multiplier);
				maxCombatValue = (int32_t)(it->maxCombatValue * multiplier);

				it->spell->castSpell(this, attackedCreature);
				if(it->isMelee)
					extraMeleeAttack = false;
#ifdef __DEBUG__
				static uint64_t prevTicks = OTSYS_TIME();
				std::cout << "doAttacking ticks: " << OTSYS_TIME() - prevTicks << std::endl;
				prevTicks = OTSYS_TIME();
#endif
			}
		}

		if(inRange)
			outOfRange = false;
		else if(it->isMelee) //melee swing out of reach
			extraMeleeAttack = true;
	}

	if(updateLook)
		updateLookDirection();

	if(resetTicks)
		attackTicks = 0;
}
Ejemplo n.º 14
0
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);
		}
	}
}