void Monster::onCreatureMove(const Creature* creature, const Tile* newTile, const Position& newPos, const Tile* oldTile, const Position& oldPos, bool teleport) { Creature::onCreatureMove(creature, newTile, newPos, oldTile, oldPos, teleport); if(creature == this) { if(isSummon()) isMasterInRange = canSee(master->getPosition()); updateTargetList(); updateIdleStatus(); } else { bool canSeeNewPos = canSee(newPos), canSeeOldPos = canSee(oldPos); if(canSeeNewPos && !canSeeOldPos) onCreatureEnter(const_cast<Creature*>(creature)); else if(!canSeeNewPos && canSeeOldPos) onCreatureLeave(const_cast<Creature*>(creature)); if(isSummon() && master == creature && canSeeNewPos) //Turn the summon on again isMasterInRange = true; updateIdleStatus(); if(!followCreature && !isSummon() && isOpponent(creature)) //we have no target lets try pick this one selectTarget(const_cast<Creature*>(creature)); } }
void Actor::onCreatureMove(const Creature* creature, const Tile* newTile, const Position& newPos, const Tile* oldTile, const Position& oldPos, bool teleport) { Creature::onCreatureMove(creature, newTile, newPos, oldTile, oldPos, teleport); if(creature == this){ if(isSummon()){ isMasterInRange = canSee(getMaster()->getPosition()); } updateTargetList(); updateIdleStatus(); /* TODO: Optimizations here if(teleport){ //do a full update of the friend/target list } else{ //partial update of the friend/target list } */ } else{ bool canSeeNewPos = canSee(newPos); bool canSeeOldPos = canSee(oldPos); if(canSeeNewPos && !canSeeOldPos){ onCreatureEnter(const_cast<Creature*>(creature)); } else if(!canSeeNewPos && canSeeOldPos){ onCreatureLeave(const_cast<Creature*>(creature)); } if(isSummon() && getMaster() == creature){ if(canSeeNewPos){ //Turn the summon on again isMasterInRange = true; } } updateIdleStatus(); if(!followCreature && !isSummon()){ //we have no target lets try pick this one if(isOpponent(creature)){ selectTarget(const_cast<Creature*>(creature)); } } } }
void Monster::onCreatureLeave(Creature* creature) { #ifdef __DEBUG__ std::clog << "onCreatureLeave - " << creature->getName() << std::endl; #endif if(isSummon() && master == creature) { if(!g_config.getBool(ConfigManager::TELEPORT_SUMMONS) && (!master->getPlayer() || !g_config.getBool(ConfigManager::TELEPORT_PLAYER_SUMMONS))) { //Turn the monster off until its master comes back isMasterInRange = false; updateIdleStatus(); } else if(!doTeleportToMaster()) teleportToMaster = true; } //update friendList if(isFriend(creature)) { CreatureList::iterator it = std::find(friendList.begin(), friendList.end(), creature); if(it != friendList.end()) { (*it)->unRef(); friendList.erase(it); } #ifdef __DEBUG__ else std::clog << "Monster: " << creature->getName() << " not found in the friendList." << std::endl; #endif } //update targetList if(isOpponent(creature)) { CreatureList::iterator it = std::find(targetList.begin(), targetList.end(), creature); if(it != targetList.end()) { (*it)->unRef(); targetList.erase(it); if(targetList.empty()) updateIdleStatus(); } #ifdef __DEBUG__ else std::clog << "Player: " << creature->getName() << " not found in the targetList." << std::endl; #endif } }
void Monster::onEndCondition(ConditionType_t type) { if(type == CONDITION_FIRE || type == CONDITION_ENERGY || type == CONDITION_POISON) updateMapCache(); updateIdleStatus(); }
void Actor::onCreatureConvinced(const Creature* convincer, const Creature* creature) { if(convincer != this && (isFriend(creature) || isOpponent(creature))){ updateTargetList(); updateIdleStatus(); } }
void Actor::onCreatureFound(Creature* creature, bool pushFront /*= false*/) { if(isFriend(creature)){ assert(creature != this); if(std::find(friendList.begin(), friendList.end(), creature) == friendList.end()){ creature->addRef(); friendList.push_back(creature); } } if(isOpponent(creature)){ assert(creature != this); if(std::find(targetList.begin(), targetList.end(), creature) == targetList.end()){ creature->addRef(); if(pushFront){ targetList.push_front(creature); } else{ targetList.push_back(creature); } } } updateIdleStatus(); }
void Actor::alwaysThink(bool b) { alwaysThink_ = b; if(alwaysThink()) setIdle(false); else updateIdleStatus(); }
void Monster::onCreatureConvinced(const Creature* convincer, const Creature* creature) { if(convincer == this || (!isFriend(creature) && !isOpponent(creature))) return; updateTargetList(); updateIdleStatus(); }
void Monster::onEndCondition(ConditionType_t type) { Creature::onEndCondition(type); //the walkCache need to be updated if the monster loose the "resistent" to the damage, see Tile::__queryAdd() if(type == CONDITION_FIRE || type == CONDITION_ENERGY || type == CONDITION_POISON) updateMapCache(); updateIdleStatus(); }
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 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::onCreatureLeave(Creature* creature) { // std::cout << "onCreatureLeave - " << creature->getName() << std::endl; if(getMaster() == creature) { //Turn the monster off until its master comes back isMasterInRange = false; updateIdleStatus(); } //update friendList if(isFriend(creature)) { CreatureList::iterator it = std::find(friendList.begin(), friendList.end(), creature); if(it != friendList.end()) { (*it)->releaseThing2(); friendList.erase(it); } #ifdef __DEBUG__ else std::cout << "Monster: " << creature->getName() << " not found in the friendList." << std::endl; #endif } //update targetList if(isOpponent(creature)) { CreatureList::iterator it = std::find(targetList.begin(), targetList.end(), creature); if(it != targetList.end()) { (*it)->releaseThing2(); targetList.erase(it); if(targetList.empty()) updateIdleStatus(); } #ifdef __DEBUG__ else std::cout << "Player: " << creature->getName() << " not found in the targetList." << std::endl; #endif } }
void Monster::onCreatureConvinced(const Creature* convincer, const Creature* creature) { if(convincer != this && (isFriend(creature) || isOpponent(creature))){ updateTargetList(); updateIdleStatus(); } #ifdef __MIN_PVP_LEVEL_APPLIES_TO_SUMMONS__ g_game.forceClientsToReloadCreature(creature); #endif }
void Monster::onCreatureEnter(Creature* creature) { if(master == creature) //Turn the summon on again { isMasterInRange = true; updateIdleStatus(); } onCreatureFound(creature, true); }
void Monster::onAddCondition(ConditionType_t type, bool hadCondition) { Creature::onAddCondition(type, hadCondition); //the walkCache need to be updated if the monster becomes "resistent" to the damage, see Tile::__queryAdd() if(type == CONDITION_FIRE || type == CONDITION_ENERGY || type == CONDITION_POISON){ updateMapCache(); } updateIdleStatus(); }
void Monster::onCreatureFound(Creature* creature, bool pushFront/* = false*/) { if (isFriend(creature)) { addFriend(creature); } if (isOpponent(creature)) { addTarget(creature, pushFront); } updateIdleStatus(); }
void Monster::onCreatureEnter(Creature* creature) { //std::cout << "onCreatureEnter - " << creature->getName() << std::endl; if(getMaster() == creature){ //Turn the summon on again isMasterInRange = true; updateIdleStatus(); } onCreatureFound(creature, true); }
void Actor::onEndCondition(const Condition* condition, bool preEnd /*= true*/) { Creature::onEndCondition(condition, preEnd); //the walkCache need to be updated if the monster loose the "resistent" to the damage, see Tile::__queryAdd() if(!preEnd && ( condition->getCombatType() == COMBAT_FIREDAMAGE || condition->getCombatType() == COMBAT_ENERGYDAMAGE || condition->getCombatType() == COMBAT_EARTHDAMAGE)) { updateMapCache(); } updateIdleStatus(); }
bool Monster::convinceCreature(Creature* creature) { Player* player = creature->getPlayer(); if(player && !player->hasFlag(PlayerFlag_CanConvinceAll) && !mType->isConvinceable) return false; Creature* oldMaster = NULL; if(isSummon()) oldMaster = master; if(oldMaster) { if(oldMaster->getPlayer() || oldMaster == creature) return false; oldMaster->removeSummon(this); } setFollowCreature(NULL); setAttackedCreature(NULL); destroySummons(); creature->addSummon(this); updateTargetList(); updateIdleStatus(); //Notify surrounding about the change SpectatorVec list; g_game.getSpectators(list, getPosition(), false, true); g_game.getSpectators(list, creature->getPosition(), true, true); isMasterInRange = true; for(SpectatorVec::iterator it = list.begin(); it != list.end(); ++it) (*it)->onCreatureConvinced(creature, this); if(spawn) { spawn->removeMonster(this); spawn = NULL; masterRadius = -1; } if(raid) { raid->unRef(); raid = NULL; } return true; }
void Monster::onCreatureAppear(const Creature* creature) { Creature::onCreatureAppear(creature); if(creature == this) { //We just spawned lets look around to see who is there. if(isSummon()) isMasterInRange = canSee(master->getPosition()); updateTargetList(); updateIdleStatus(); } else onCreatureEnter(const_cast<Creature*>(creature)); }
void Actor::onCreatureAppear(const Creature* creature, bool isLogin) { Creature::onCreatureAppear(creature, isLogin); if(creature == this){ //We just spawned lets look around to see who is there. if(isSummon()){ isMasterInRange = canSee(getMaster()->getPosition()); } updateTargetList(); updateIdleStatus(); } else{ onCreatureEnter(const_cast<Creature*>(creature)); } }
void Npc::onRemoveCreature(Creature* creature, bool isLogout) { Creature::onRemoveCreature(creature, isLogout); if (creature == this) { closeAllShopWindows(); if (npcEventHandler) { npcEventHandler->onCreatureDisappear(creature); } } else if (Player* player = creature->getPlayer()) { if (npcEventHandler) { npcEventHandler->onCreatureDisappear(creature); } spectators.erase(player); updateIdleStatus(); } }
void Monster::onCreatureAppear(Creature* creature, bool isLogin) { Creature::onCreatureAppear(creature, isLogin); if (mType->info.creatureAppearEvent != -1) { // onCreatureAppear(self, creature) LuaScriptInterface* scriptInterface = mType->info.scriptInterface; if (!scriptInterface->reserveScriptEnv()) { std::cout << "[Error - Monster::onCreatureAppear] Call stack overflow" << std::endl; return; } ScriptEnvironment* env = scriptInterface->getScriptEnv(); env->setScriptId(mType->info.creatureAppearEvent, scriptInterface); lua_State* L = scriptInterface->getLuaState(); scriptInterface->pushFunction(mType->info.creatureAppearEvent); LuaScriptInterface::pushUserdata<Monster>(L, this); LuaScriptInterface::setMetatable(L, -1, "Monster"); LuaScriptInterface::pushUserdata<Creature>(L, creature); LuaScriptInterface::setCreatureMetatable(L, -1, creature); if (scriptInterface->callFunction(2)) { return; } } if (creature == this) { //We just spawned lets look around to see who is there. if (isSummon()) { isMasterInRange = canSee(getMaster()->getPosition()); } updateTargetList(); updateIdleStatus(); } else { onCreatureEnter(creature); } }
void Npc::onCreatureAppear(Creature* creature, bool isLogin) { Creature::onCreatureAppear(creature, isLogin); if (creature == this) { if (walkTicks > 0) { addEventWalk(); } if (npcEventHandler) { npcEventHandler->onCreatureAppear(creature); } } else if (Player* player = creature->getPlayer()) { if (npcEventHandler) { npcEventHandler->onCreatureAppear(creature); } spectators.insert(player); updateIdleStatus(); } }
void Monster::onCreatureLeave(Creature* creature) { // std::cout << "onCreatureLeave - " << creature->getName() << std::endl; if (getMaster() == creature) { //Take random steps and only use defense abilities (e.g. heal) until its master comes back isMasterInRange = false; } //update friendList if (isFriend(creature)) { removeFriend(creature); } //update targetList if (isOpponent(creature)) { removeTarget(creature); if (targetList.empty()) { updateIdleStatus(); } } }
void Monster::onCreatureAppear(const Creature* creature) { Creature::onCreatureAppear(creature); if(creature == this) { //We just spawned lets look around to see who is there. if(isSummon()) isMasterInRange = canSee(getMaster()->getPosition()); setStorage(510, mType->realName); // sistema de shiny nomes 2.0 CreatureEventList spawn = getCreatureEvents(CREATURE_EVENT_SPAWN); for(CreatureEventList::iterator it = spawn.begin(); it != spawn.end(); ++it) (*it)->executeOnSpawn(this); updateTargetList(); updateIdleStatus(); } else onCreatureEnter(const_cast<Creature*>(creature)); }
void Npc::onCreatureMove(Creature* creature, const Tile* newTile, const Position& newPos, const Tile* oldTile, const Position& oldPos, bool teleport) { Creature::onCreatureMove(creature, newTile, newPos, oldTile, oldPos, teleport); if (creature == this || creature->getPlayer()) { if (npcEventHandler) { npcEventHandler->onCreatureMove(creature, oldPos, newPos); } if (creature != this) { Player* player = creature->getPlayer(); // if player is now in range, add to spectators list, otherwise erase if (player->canSee(position)) { spectators.insert(player); } else { spectators.erase(player); } updateIdleStatus(); } } }
bool Monster::convinceCreature(Creature* creature) { Player* player = creature->getPlayer(); if(player && !player->hasFlag(PlayerFlag_CanConvinceAll)) { if(!mType->isConvinceable) return false; } if(isSummon()) { if(getMaster()->getPlayer()) return false; else if(getMaster() != creature) { Creature* oldMaster = getMaster(); oldMaster->removeSummon(this); creature->addSummon(this); setFollowCreature(NULL); setAttackedCreature(NULL); //destroy summons for(std::list<Creature*>::iterator cit = summons.begin(); cit != summons.end(); ++cit) { (*cit)->changeHealth(-(*cit)->getHealth()); (*cit)->setMaster(NULL); (*cit)->releaseThing2(); } summons.clear(); isMasterInRange = true; updateTargetList(); updateIdleStatus(); //Notify surrounding about the change SpectatorVec list; g_game.getSpectators(list, getPosition(), false, true); g_game.getSpectators(list, creature->getPosition(), true, true); for(SpectatorVec::iterator it = list.begin(); it != list.end(); ++it) (*it)->onCreatureConvinced(creature, this); if(spawn) { spawn->removeMonster(this); spawn = NULL; masterRadius = -1; } return true; } } else { creature->addSummon(this); setFollowCreature(NULL); setAttackedCreature(NULL); for(std::list<Creature*>::iterator cit = summons.begin(); cit != summons.end(); ++cit) { (*cit)->changeHealth(-(*cit)->getHealth()); (*cit)->setMaster(NULL); (*cit)->releaseThing2(); } summons.clear(); isMasterInRange = true; updateTargetList(); updateIdleStatus(); //Notify surrounding about the change SpectatorVec list; g_game.getSpectators(list, getPosition(), false, true); g_game.getSpectators(list, creature->getPosition(), true, true); for(SpectatorVec::iterator it = list.begin(); it != list.end(); ++it) (*it)->onCreatureConvinced(creature, this); if(spawn) { spawn->removeMonster(this); spawn = NULL; masterRadius = -1; } 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 Actor::convinceCreature(Creature* creature) { Player* player = creature->getPlayer(); if(player && !player->hasFlag(PlayerFlag_CanConvinceAll)){ if(!cType.isConvinceable()){ return false; } } if(isPlayerSummon()){ return false; } else if(isSummon()){ if(getMaster() != creature){ Creature* oldMaster = getMaster(); oldMaster->removeSummon(this); creature->addSummon(this); setFollowCreature(NULL); setAttackedCreature(NULL); //destroy summons destroySummons(); isMasterInRange = true; updateTargetList(); updateIdleStatus(); //Notify surrounding about the change SpectatorVec list; g_game.getSpectators(list, getPosition(), false, true); g_game.getSpectators(list, creature->getPosition(), true, true); for(SpectatorVec::iterator it = list.begin(); it != list.end(); ++it){ (*it)->onCreatureConvinced(creature, this); } if(spawn){ spawn->removeMonster(this); spawn = NULL; masterRadius = -1; } return true; } } else{ creature->addSummon(this); setFollowCreature(NULL); setAttackedCreature(NULL); destroySummons(); isMasterInRange = true; updateTargetList(); updateIdleStatus(); //Notify surrounding about the change SpectatorVec list; g_game.getSpectators(list, getPosition(), false, true); g_game.getSpectators(list, creature->getPosition(), true, true); for(SpectatorVec::iterator it = list.begin(); it != list.end(); ++it){ (*it)->onCreatureConvinced(creature, this); } if(spawn){ spawn->removeMonster(this); spawn = NULL; masterRadius = -1; } return true; } return false; }