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; goToFollowCreature(); } #ifndef __GROUPED_ATTACKS__ onAttacking(interval / EVENT_CREATURECOUNT); #else onAttacking(interval); #endif executeConditions(interval); CreatureEventList thinkEvents = getCreatureEvents(CREATURE_EVENT_THINK); for(CreatureEventList::iterator it = thinkEvents.begin(); it != thinkEvents.end(); ++it) (*it)->executeThink(this, interval); }
void Creature::onChangeZone(ZoneType zone) { if(attackedCreature){ if(zone == ZONE_PROTECTION){ internalCreatureDisappear(attackedCreature, false); } } }
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()); CreatureEventList disappearEvents = getCreatureEvents(CREATURE_EVENT_DISAPPEAR); for(CreatureEventList::iterator it = disappearEvents.begin(); it != disappearEvents.end(); ++it) (*it)->executeDisappear(this, creature); } }
void Creature::onThink(uint32_t interval) { if(!isMapLoaded && useCacheMap()){ isMapLoaded = true; updateMapCache(); } if(followCreature && getMaster() != followCreature && !canSeeCreature(followCreature)){ internalCreatureDisappear(followCreature, false); } if(attackedCreature && getMaster() != 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); g_game.onCreatureThink(this, interval); }
void Creature::onCreatureDisappear(const Creature* creature, bool isLogout) { internalCreatureDisappear(creature, true); if(creature == this){ // } else if(isMapLoaded){ if(creature->getPosition().z == getPosition().z){ updateTileCache(creature->getParentTile(), creature->getPosition()); } } }
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; if(teleport){ stopEventWalk(); } else{ if(oldPos.z != newPos.z){ //floor change extra cost lastStepCost = 2; } else if(std::abs(newPos.x - oldPos.x) >=1 && std::abs(newPos.y - oldPos.y) >= 1){ //diagonal extra cost lastStepCost = 2; } } if(!summons.empty()){ //check if any of our summons is out of range (+/- 2 floors or 30 tiles away) std::list<Creature*> despawnList; std::list<Creature*>::iterator cit; for(cit = summons.begin(); cit != summons.end(); ++cit){ const Position pos = (*cit)->getPosition(); if( (std::abs(pos.z - newPos.z) > 2) || (std::max(std::abs((newPos.x) - pos.x), std::abs((newPos.y - 1) - pos.y)) > 30) ){ despawnList.push_back((*cit)); } } for(cit = despawnList.begin(); cit != despawnList.end(); ++cit){ g_game.removeCreature((*cit), true); } } if(newTile->getZone() != oldTile->getZone()){ onChangeZone(getZone()); } //update map cache if(isMapLoaded){ if(teleport || oldPos.z != newPos.z){ updateMapCache(); } else{ Tile* tile; const Position& myPos = getPosition(); Position pos; 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.getParentTile(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.getParentTile(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; int32_t endy = mapWalkHeight - 1; int32_t 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.getParentTile(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; int32_t endy = mapWalkHeight - 1; int32_t 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.getParentTile(myPos.x - ((mapWalkWidth - 1) / 2), myPos.y + y, myPos.z); updateTileCache(tile, -((mapWalkWidth - 1) / 2), y); } } updateTileCache(oldTile, oldPos); #ifdef __DEBUG__ validateMapCache(); #endif } } } 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 = false; g_dispatcher.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())){ internalCreatureDisappear(attackedCreature, false); } else{ if(hasExtraSwing()){ //our target is moving lets see if we can get in hit g_dispatcher.addTask(createTask( boost::bind(&Game::checkCreatureAttack, &g_game, getID()))); } if(newTile->getZone() != oldTile->getZone()){ onAttackedCreatureChangeZone(attackedCreature->getZone()); } } } }
void Creature::onCreatureMove(const Creature* creature, const Tile* newTile, const Position& newPos, const Tile* oldTile, const Position& oldPos, bool teleport) { if(creature == this) { if(!oldTile->floorChange() && !oldTile->positionChange()) setLastPosition(oldPos); lastStep = OTSYS_TIME(); lastStepCost = 1; if(!teleport) { if(std::abs(newPos.x - oldPos.x) >= 1 && std::abs(newPos.y - oldPos.y) >= 1) lastStepCost = 3; } else stopEventWalk(); if(!summons.empty() && (!g_config.getBool(ConfigManager::TELEPORT_SUMMONS) || (g_config.getBool(ConfigManager::TELEPORT_PLAYER_SUMMONS) && !getPlayer()))) { std::list<Creature*>::iterator cit; std::list<Creature*> despawnList; for(cit = summons.begin(); cit != summons.end(); ++cit) { const Position pos = (*cit)->getPosition(); if((std::abs(pos.z - newPos.z) > 2) || (std::max(std::abs(( newPos.x) - pos.x), std::abs((newPos.y - 1) - pos.y)) > 30)) despawnList.push_back(*cit); } for(cit = despawnList.begin(); cit != despawnList.end(); ++cit) g_game.removeCreature((*cit), true); } 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()) onTargetChangeZone(attackedCreature->getZone()); } else internalCreatureDisappear(attackedCreature, false); } }
void Creature::onTargetChangeZone(ZoneType_t zone) { if(zone == ZONE_PROTECTION) internalCreatureDisappear(attackedCreature, false); }