void Creature::onDie() { DeathList killers = getKillers(g_config.getNumber(ConfigManager::DEATH_ASSIST_COUNT)); for(DeathList::const_iterator it = killers.begin(); it != killers.end(); ++it){ if(it->isCreatureKill()){ Creature* attacker = it->getKillerCreature(); if(attacker){ attacker->onKilledCreature(this); } } } for(CountMap::iterator it = damageMap.begin(); it != damageMap.end(); ++it){ if(Creature* attacker = g_game.getCreatureByID((*it).first)){ attacker->onAttackedCreatureKilled(this); } } Item* corpse = dropCorpse(); die(); g_game.onCreatureDeath(this, corpse, (killers.front().isCreatureKill()? killers.front().getKillerCreature() : NULL)); if(corpse){ Player* killer = g_game.getPlayerByID(corpse->getCorpseOwner()); if(killer){ killer->broadcastLoot(this, corpse->getContainer()); } } if(getMaster()){ getMaster()->removeSummon(this); } }
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(getMaster()->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() && getMaster() == 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 Monster::updateIdleStatus() { //heightMinimum is declared static to avoid //several calls for getNumber (updateIdleStatus is called often) static int heightMinimum = 0; if (heightMinimum <= 0) heightMinimum = std::max(g_config.getNumber(ConfigManager::HEIGHT_MINIMUM_FOR_IDLE),(int64_t)1); bool idle = false; semiIdle = false; if(conditions.empty()){ if(isSummon()){ if(!isMasterInRange){ idle = true; } else if(getMaster()->getMonster() && getMaster()->getMonster()->getIdleStatus()){ idle = true; } } else{ idle = targetList.empty(); semiIdle = !idle; for(CreatureList::iterator it = targetList.begin(); it != targetList.end(); ++it){ if (std::abs((*it)->getPosition().z - getPosition().z) < heightMinimum) { semiIdle = false; break; } } } } setIdle(idle); }
bool Monster::isFriend(const Creature* creature) const { if (isSummon() && getMaster()->getPlayer()) { const Player* masterPlayer = getMaster()->getPlayer(); const Player* tmpPlayer = nullptr; if (creature->getPlayer()) { tmpPlayer = creature->getPlayer(); } else { const Creature* creatureMaster = creature->getMaster(); if (creatureMaster && creatureMaster->getPlayer()) { tmpPlayer = creatureMaster->getPlayer(); } } if (tmpPlayer && (tmpPlayer == getMaster() || masterPlayer->isPartner(tmpPlayer))) { return true; } } else if (creature->getMonster() && !creature->isSummon()) { return true; } return false; }
int Monster::cleanMobForSaving() { // No saving pets! if(isPet()) return(-1); // Clear the inventory clearMobInventory(); // Clear any flags that shouldn't be set clearFlag(M_WILL_BE_LOGGED); // // If the creature is possessed, clean that up if(flagIsSet(M_DM_FOLLOW)) { clearFlag(M_DM_FOLLOW); Player* master; if(getMaster() != nullptr && (master = getMaster()->getAsPlayer()) != nullptr) { master->clearFlag(P_ALIASING); master->getAsPlayer()->setAlias(0); master->print("%1M's soul was saved.\n", this); removeFromGroup(false); } } // Success return(1); }
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 Creature::onRemoved() { removeList(); setRemoved(); if(getMaster() && !getMaster()->isRemoved()){ getMaster()->removeSummon(this); } }
void Creature::onCreatureDisappear(const Creature* creature, uint32_t stackpos, bool isLogout) { onCreatureDisappear(creature, true); if (creature == this) { if (getMaster() && !getMaster()->isRemoved()) { getMaster()->removeSummon(this); } } else if (isMapLoaded) { if (creature->getPosition().z == getPosition().z) { updateTileCache(creature->getTile(), creature->getPosition()); } } }
bool Creature::onKilledCreature(Creature* target, bool lastHit/* = true*/) { if (getMaster()) { getMaster()->onKilledCreature(target); } //scripting event - onKill const CreatureEventList& killEvents = getCreatureEvents(CREATURE_EVENT_KILL); for (CreatureEvent* killEvent : killEvents) { killEvent->executeOnKill(this, target); } return false; }
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::cout << "onCreatureLeave - " << creature->getName() << std::endl; #endif if(isSummon() && getMaster() == creature) { if(!g_config.getBool(ConfigManager::TELEPORT_SUMMONS) && (!getMaster()->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::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)->unRef(); targetList.erase(it); if(targetList.empty()) updateIdleStatus(); } #ifdef __DEBUG__ else std::cout << "Player: " << creature->getName() << " not found in the targetList." << std::endl; #endif } }
bool Monster::isFriend(const Creature* creature) { if(!isSummon() || !getMaster()->getPlayer()) return creature->getMonster() && !creature->isSummon(); const Player* tmpPlayer = NULL; if(creature->getPlayer()) tmpPlayer = creature->getPlayer(); else if(creature->getMaster() && creature->getMaster()->getPlayer()) tmpPlayer = creature->getMaster()->getPlayer(); const Player* masterPlayer = getMaster()->getPlayer(); return tmpPlayer && (tmpPlayer == getMaster() || masterPlayer->isPartner(tmpPlayer)); }
bool Monster::isOpponent(const Creature* creature) const { if (isSummon() && getMaster()->getPlayer()) { if (creature != getMaster()) { return true; } } else { if ((creature->getPlayer() && !creature->getPlayer()->hasFlag(PlayerFlag_IgnoredByMonsters)) || (creature->getMaster() && creature->getMaster()->getPlayer())) { return true; } } return false; }
void Monster::updateIdleStatus() { bool idle = false; if(conditions.empty()) { if(isSummon()) { if(!isMasterInRange || (getMaster()->getMonster() && getMaster()->getMonster()->getIdleStatus())) idle = true; } else if(targetList.empty()) idle = true; } setIdle(idle); }
bool Creature::onKilledCreature(Creature* target, bool lastHit/* = true*/) { if (getMaster()) { getMaster()->onKilledCreature(target); } //scripting event - onKill CreatureEventList killEvents = getCreatureEvents(CREATURE_EVENT_KILL); for (CreatureEventList::const_iterator it = killEvents.begin(), end = killEvents.end(); it != end; ++it) { (*it)->executeOnKill(this, target); } return false; }
bool Monster::addEnemy(Creature* target, bool print) { if(isEnemy(target)) return false; if(print) { if(aggroString[0]) broadcast(nullptr, getRoomParent(), "%M says, \"%s.\"", this, aggroString); target->printColor("^r%M attacks you.\n", this); broadcast(target->getSock(), getRoomParent(), "%M attacks %N.", this, target); } if(target->isPlayer()) { // take pity on these people if(target->isEffected("petrification") || target->isUnconscious()) return(0); // pets should not attack master if(isPet() && getMaster() == target) return(false); } if(target->isPet()) { addEnemy(target->getMaster()); } adjustThreat(target, 0); return(true); }
void Monster::getPathSearchParams(const Creature* creature, FindPathParams& fpp) const { Creature::getPathSearchParams(creature, fpp); fpp.minTargetDist = 1; fpp.maxTargetDist = mType->targetDistance; 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.clearSight = false; fpp.keepDistance = true; fpp.fullPathSearch = false; } else if(mType->targetDistance <= 1) fpp.fullPathSearch = true; else fpp.fullPathSearch = !canUseAttack(getPosition(), creature); }
void Monster::onCreatureAppear(const Creature* creature, bool isLogin) { if(creature == getMaster()){ //wake up if necessary startThink(); } }
void FocusCameraClient::exposureStarted (bool expectImage) { if (exe == NULL) { queCommand (new rts2core::CommandExposure (getMaster (), this, bop >= 0 ? bop : 0)); } rts2image::DevClientCameraFoc::exposureStarted (expectImage); }
void Actor::onAttackedCreatureDrainMana(Creature* target, int32_t points) { Creature::onAttackedCreatureDrainMana(target, points); if(isSummon()){ getMaster()->onSummonAttackedCreatureDrainMana(this, target, points); } }
void Actor::onAttackedCreature(Creature* target) { Creature::onAttackedCreature(target); if(isSummon()){ getMaster()->onSummonAttackedCreature(this, target); } }
void Monster::onAttackedCreatureDrainHealth(Creature* target, int32_t points) { Creature::onAttackedCreatureDrainHealth(target, points); if(isSummon()){ getMaster()->onSummonAttackedCreatureDrainHealth(this, target, points); } }
void Creature::onGainExperience(uint64_t gainExp, bool fromMonster) { if(gainExp > 0){ if(getMaster()){ gainExp = gainExp / 2; getMaster()->onGainExperience(gainExp, fromMonster); //get the real experience gained to show on screen, since player rate counts for their summons if(getMaster()->getPlayer()){ getMaster()->getPlayer()->getGainExperience(gainExp, fromMonster); } } std::stringstream strExp; strExp << gainExp; g_game.addAnimatedText(getPosition(), TEXTCOLOR_WHITE_EXP, strExp.str()); } }
void Creature::onThink(uint32_t interval) { if (!isMapLoaded && useCacheMap()) { isMapLoaded = true; updateMapCache(); } if (followCreature && getMaster() != followCreature && !canSeeCreature(followCreature)) { onCreatureDisappear(followCreature, false); } if (attackedCreature && getMaster() != attackedCreature && !canSeeCreature(attackedCreature)) { onCreatureDisappear(attackedCreature, false); } blockTicks += interval; if (blockTicks >= 1000) { blockCount = std::min<uint32_t>(blockCount + 1, 2); blockTicks = 0; } if (followCreature) { walkUpdateTicks += interval; if (forceUpdateFollowPath || walkUpdateTicks >= 2000) { walkUpdateTicks = 0; forceUpdateFollowPath = false; isUpdatingPath = true; } } if (isUpdatingPath) { isUpdatingPath = false; goToFollowCreature(); } //scripting event - onThink CreatureEventList thinkEvents = getCreatureEvents(CREATURE_EVENT_THINK); for (CreatureEventList::const_iterator it = thinkEvents.begin(), end = thinkEvents.end(); it != end; ++it) { (*it)->executeOnThink(this, interval); } }
ParameterMapSharedPtr Instance::getParameters() const throw (Error) { if(!getMaster()) { return ParameterMapSharedPtr(); } ParameterMapSharedPtr params = mMaster->getParameters(); if(!params->isContextRegistered(mMyContext)) { params->registerContext(mMyContext, mMaster->getParameterContext()); } return params; }
void Monster::onCreatureEnter(Creature* creature) { if(getMaster() == creature) //Turn the summon on again { isMasterInRange = true; updateIdleStatus(); } onCreatureFound(creature, true); }
void Monster::onCreatureEnter(Creature* creature) { // std::cout << "onCreatureEnter - " << creature->getName() << std::endl; if (getMaster() == creature) { //Follow master again isMasterInRange = true; } onCreatureFound(creature, true); }
void Creature::onGainExperience(uint64_t gainExp, Creature* target) { if (gainExp != 0 && getMaster()) { gainExp = gainExp / 2; getMaster()->onGainExperience(gainExp, target); const Position& targetPos = getPosition(); std::ostringstream ssExp; ssExp << ucfirst(getNameDescription()) << " gained " << gainExp << " experience points."; std::string strExp = ssExp.str(); SpectatorVec list; g_game.getSpectators(list, targetPos, false, true); for (Creature* spectator : list) { spectator->getPlayer()->sendExperienceMessage(MSG_EXPERIENCE_OTHERS, strExp, targetPos, gainExp, TEXTCOLOR_WHITE_EXP); } } }
void Actor::onCreatureEnter(Creature* creature) { //std::cout << "onCreatureEnter - " << creature->getName() << std::endl; if(getMaster() == creature){ //Turn the summon on again isMasterInRange = true; } onCreatureFound(creature, true); }
bool Monster::doTeleportToMaster() { const Position& tmp = getPosition(); if(g_game.internalTeleport(this, g_game.getClosestFreeTile(this, getMaster()->getPosition(), true), false) != RET_NOERROR) return false; //g_game.addMagicEffect(tmp, MAGIC_EFFECT_POFF); //g_game.addMagicEffect(getPosition(), MAGIC_EFFECT_SOUND_YELLOW); return true; }