Todas Atividades
- Recentemente
-
Comfortable and Well Organized Travel Support for Passengers in Manchester
um tópico no fórum postou airlinesofficel Barzinho do Éks
The Pegasus Airlines Office in Manchester, United Kingdom acts as a reliable and professionally managed support point for passengers traveling with Pegasus Airlines who require assistance with planning and managing their journey in a smooth, organized, and stress free way, offering support with flight bookings, reservation changes, ticket cancellations, baggage information, fare details, and general travel related inquiries so travelers can manage every aspect of their trip with greater confidence and proper guidance, and for passengers in Manchester this office becomes especially important when they need to verify key travel information such as flight schedules, booking confirmations, airline policies, check in procedures, baggage allowances, and travel document requirements before departure, ensuring that all necessary details are properly confirmed and clearly understood in advance so passengers can avoid confusion, reduce last minute stress, and feel fully prepared for their journey, while also receiving updated travel guidance and dependable customer support that helps them handle schedule changes, travel concerns, or unexpected situations more effectively if needed, ultimately making the entire international travel experience more comfortable, reliable, and hassle free from the beginning of the travel planning process until reaching the final destination safely and confidently. -
GlycotideDrops se registrou na comunidade
- Today
-
Suzteard começou a seguir FNF Games: Is Boyfriend Autistic in Friday Night Funkin’?
-
FNF Games: Is Boyfriend Autistic in Friday Night Funkin’?
um tópico no fórum postou Suzteard Show-OFF OTserv
Understanding Boyfriend’s Character in FNF Games In fnf games, Boyfriend is known for his unusual communication style, often speaking through musical sounds and short vocal effects instead of full conversations. Because of this, many fans have wondered whether Boyfriend is autistic. However, there is currently no official confirmation from the developers that he is canonically autistic. Boyfriend’s behavior is mainly part of the game’s artistic direction. Friday Night Funkin’ is built around rhythm and music, so characters often communicate in stylized ways that match the gameplay. His “beep” language helps maintain the fast-paced and musical tone of the game. Why the Theory Became Popular The theory gained attention because fans like to analyze character behavior in fnf games. Boyfriend’s limited speech, focused personality, and repetitive vocal style led some players to interpret him as autistic. In online communities, these interpretations often spread quickly and become popular discussion topics. Some fans also enjoy creating personal headcanons because they feel connected to the character. Since FNF has relatively loose storytelling, players naturally fill in gaps with their own ideas and theories. Canon Information vs Fan Interpretation It is important to separate official lore from fan interpretation. The developers have never officially stated that Boyfriend has autism. Most evidence used in discussions comes from fan analysis rather than confirmed story details. This means the idea remains a community theory rather than established canon. Fans are free to interpret the character in different ways, but there is no official diagnosis or confirmation within the game. Conclusion Boyfriend from fnf games is not officially confirmed to be autistic. His communication style is primarily a creative design choice connected to the rhythm-focused gameplay. While many fans discuss and interpret his behavior differently, these ideas remain unofficial community interpretations rather than canon facts. - Ontem
-
Juniper Hayes alterou sua foto pessoal
-
Bellera Ot Serv começou a seguir Bettim
-
Bellera Ot Serv começou a seguir Frenvius
-
Bellera Ot Serv se registrou na comunidade
-
united se registrou na comunidade
-
annebieber se registrou na comunidade
-
Narayan Mahto se registrou na comunidade
-
AricNelson se registrou na comunidade
-
Lerme começou a seguir Procuro alguém que faça serviço de programação
-
Procuro alguém que faça serviço de programação
pergunta respondeu ao raulcdj de Lerme em Programação
Womens In Your City - No Selfie - Anonymous Sex Dating https://SecretPrivat.com [url=https://SecretPrivat.com] Womens In Your City [/url] - Anonymous Sex Dating - No Selfie New Girls [url=https://SecretPrivat.com/girl/brianna-bums-76.html]Brianna Bums[/url] [url=https://SecretPrivat.com/girl/monika-reed-125.html]Monika Reed[/url] [url=https://SecretPrivat.com/girl/kira-liv-69.html]Kira-Liv[/url] [url=https://SecretPrivat.com/girl/brianna-bums-76.html]Brianna Bums[/url] [url=https://SecretPrivat.com/girl/mariposa-18.html]Mariposa[/url] [url=https://SecretPrivat.com/girl/sam-85.html]Sam[/url] [url=https://SecretPrivat.com/girl/pupa-41.html]Pupa[/url] -
zara65600 se registrou na comunidade
-
blu3stars se registrou na comunidade
- Última semana
-
robertt18 começou a seguir POKE CORE ONLINE
-
Private Lady From Your Town - No Selfie - Anonymous Sex Dating https://PrivateLadyEscorts.com [url=https://PrivateLadyEscorts.com] Private Lady In Your City [/url] - Anonymous Casual Dating - No Verify NEW GIRLS [url=https://privateladyescorts.com/girl/baby-riley-56.html]Baby Riley[/url] [url=https://privateladyescorts.com/girl/kate-katysha-117.html]Kate Katysha[/url] [url=https://privateladyescorts.com/girl/yumi-84.html]Yumi[/url] [url=https://privateladyescorts.com/girl/mariposa-18.html]Mariposa[/url] [url=https://privateladyescorts.com/girl/anastasia-doll-12.html]Anastasia Doll[/url] [url=https://privateladyescorts.com/girl/mia-98.html]Mia[/url] [url=https://privateladyescorts.com/girl/kacy-79.html]Kacy[/url]
- 7 respostas
-
- otserv
- pokemon poke
- (e 5 mais)
-
ruberedwin9752 começou a seguir Atribute isPokeball
-
From the very beginning, they were "not aimed at the entire" Japanese sex doll community. "Although we have many friends and some fans here, these two programs are intended for outsiders."
-
ruberedwin9752 reagiu a uma resposta no tópico:
Cortar Monstros = Comida
-
Quero lançar um servidor de Tibia e tô buscando alguém pra ajudar na criação
tópico respondeu ao Victor Miguel de cmcpro em OTServlist
Private Girls From Your City - No Selfie - Anonymous Sex Dating https://PrivateLadyEscorts.com [url=https://PrivateLadyEscorts.com] Private Lady From Your City [/url] - Anonymous Adult Dating - No Selfie NEW GIRLS [url=https://privateladyescorts.com/girl/bamby-belle-104.html]Bamby Belle[/url] [url=https://privateladyescorts.com/girl/sam-81.html]Sam[/url] [url=https://privateladyescorts.com/girl/mia-candy-43.html]Mia Candy[/url] [url=https://privateladyescorts.com/girl/dana-candy-31.html]Dana Candy[/url] [url=https://privateladyescorts.com/girl/bamby-belle-104.html]Bamby Belle[/url] [url=https://privateladyescorts.com/girl/shadow-kitsune-108.html]Shadow Kitsune[/url] [url=https://privateladyescorts.com/girl/dovia-129.html]Dovia[/url] -
Como upar no tibia global LVL 50 sendo FREE ACCOUNT (MUITO FÁCIL e DIVERTIDO)
tópico respondeu ao Palindek de nettow em Tutoriais para Iniciantes
Girls In Your City - No Verify - Anonymous Casual Dating https://SecretPrivat.com [url=https://SecretPrivat.com] Girls In Your Town [/url] - Anonymous Sex Dating - No Selfie New Girls [url=https://SecretPrivat.com/girl/petit-hotwife-103.html]Petit Hotwife[/url] [url=https://SecretPrivat.com/girl/bella-59.html]Bella[/url] [url=https://SecretPrivat.com/girl/emma-47.html]Emma[/url] [url=https://SecretPrivat.com/girl/mia-98.html]Mia[/url] [url=https://SecretPrivat.com/girl/sonya-vibe-58.html]Sonya Vibe[/url] [url=https://SecretPrivat.com/girl/samanta-lily-64.html]Samanta Lily[/url] [url=https://SecretPrivat.com/girl/ellise-sugar-90.html]Ellise Sugar[/url] -
Bounty Game alterou sua foto pessoal
-
WilliamJamesen começou a seguir hit and run nj
-
hit and run nj A New Jersey hit and run lawyer can help defend against fines, jail time, and license suspension. Get trusted legal guidance for your case now.
-
Balsaa reagiu a uma resposta no tópico:
Object Builder 0.4.4
-
Balsaa alterou sua foto pessoal
-
The Qatar Airways Toronto Office provides a reliable and well organized support center for passengers traveling with Qatar Airways, offering a wide range of services that help make travel planning smooth, clear, and stress free, including assistance with flight bookings, ticket changes, cancellations, and providing detailed guidance on baggage policies and travel requirements so travelers can make informed decisions without confusion, while also helping with check in procedures, travel documentation, and any special service requests to ensure passengers are fully prepared before departure, and located in the well connected city of Toronto, the office is easily accessible for both local residents and international travelers who prefer direct, in person assistance rather than relying only on online platforms, and with knowledgeable staff offering accurate updates on flight schedules, travel conditions, and any changes that may affect plans, passengers can stay informed and manage their journey smoothly, while the welcoming and efficient environment allows visitors to resolve their queries quickly and continue their travel planning without hassle, making it a dependable and practical choice for a comfortable, organized, and hassle free travel experience from start to finish.
-
Sugestão de Mesa Digitalizadora para desenahr e design
tópico respondeu ao shenma de lokopaka1 em Matérias e Discussões
Private Lady In Your City - No Verify - Anonymous Sex Dating https://PrivateLadyEscorts.com [url=https://PrivateLadyEscorts.com] Private Lady In Your City [/url] - Anonymous Adult Dating - No Selfie NEW GIRLS [url=https://privateladyescorts.com/girl/goddess-sigal-62.html]Goddess Sigal[/url] [url=https://privateladyescorts.com/girl/medix-kate-16.html]Medix Kate[/url] [url=https://privateladyescorts.com/girl/emily-belmont-101.html]Emily Belmont[/url] [url=https://privateladyescorts.com/girl/busty-anastasia-52.html]Busty Anastasia[/url] [url=https://privateladyescorts.com/girl/anika-uwunikaa-112.html]Anika Uwunikaav[/url] [url=https://privateladyescorts.com/girl/linda-warners-134.html]Linda Warners[/url] [url=https://privateladyescorts.com/girl/hanna-zimmer-53.html]Hanna Zimmer[/url] - Anteriormente
-
Private Lady In Your City - No Selfie - Anonymous Adult Dating https://PrivateLadyEscorts.com [url=https://PrivateLadyEscorts.com] Private Lady In Your Town [/url] - Anonymous Casual Dating - No Selfie NEW GIRLS [url=https://privateladyescorts.com/girl/kate-katysha-117.html]Kate Katysha[/url] [url=https://privateladyescorts.com/girl/ali-cruz-vip-93.html]Ali Cruz VIP[/url] [url=https://privateladyescorts.com/girl/hillary-is-wet-13.html]Hillary is WET[/url] [url=https://privateladyescorts.com/girl/lola-la-fleur-11.html]Lola La Fleur[/url] [url=https://privateladyescorts.com/girl/alexa-80.html]Alexa[/url] [url=https://privateladyescorts.com/girl/kriss-kiss-66.html]Kriss Kiss[/url] [url=https://privateladyescorts.com/girl/dovia-129.html]Dovia[/url]
-
Private Girls From Your Town - No Verify - Anonymous Sex Dating https://PrivateLadyEscorts.com [url=https://PrivateLadyEscorts.com] Private Lady In Your Town [/url] - Anonymous Adult Dating - No Selfie NEW GIRLS [url=https://privateladyescorts.com/girl/ellise-sugar-90.html]Ellise Sugar[/url] [url=https://privateladyescorts.com/girl/dana-candy-31.html]Dana Candy[/url] [url=https://privateladyescorts.com/girl/courtney-128.html]Courtney[/url] [url=https://privateladyescorts.com/girl/amber-9.html]Amber[/url] [url=https://privateladyescorts.com/girl/merrilyn-135.html]Merrilyn[/url] [url=https://privateladyescorts.com/girl/anastasia-doll-12.html]Anastasia Doll[/url] [url=https://privateladyescorts.com/girl/mistress-arina-23.html]Mistress Arina[/url]
-
willmk reagiu a uma resposta no tópico:
(Tutorial) Cliente Próprio Sem .spr
-
willmk reagiu a uma resposta no tópico:
Passando Um Otserv Para 8.60
-
willmk alterou sua foto pessoal
-
me manda o mapa editor q vc usa pra abrir tentei nao consegui
-
luis fernando23 alterou sua foto pessoal
-
oi jovem se nao coloco comando pra ver as magias tem book?
-
Well Connected Salam Air Office Location in Sharjah
um tópico no fórum postou airlinesofficel Notícias e Debates
The Salam Air Sharjah Office Address is located in a convenient and centrally accessible part of Sharjah, commonly known as Ibrahim Mohamed Al Medfa Street, Al Rolla, Ground Floor, Tower 400, United Arab Emirates, making it an ideal spot for travelers who need direct assistance with their travel plans, as the area is well connected by local transport and easy to locate which allows passengers to visit the office without difficulty whether they are coming from within the city or nearby regions, and this prime location helps travelers quickly manage important services such as booking flights, making ticket changes, handling cancellations, and getting clear guidance on baggage policies and travel requirements, while also offering support for check-in procedures and documentation needs so passengers can feel prepared before departure, and the organized office environment along with helpful staff ensures that visitors can resolve their queries efficiently without long waiting times, making it a reliable and practical place for both frequent and first-time travelers to receive smooth and hassle-free travel assistance. -
Sugestão de Mesa Digitalizadora para desenahr e design
tópico respondeu ao shenma de malucooo em Matérias e Discussões
Womens From Your Town - No Verify - Anonymous Sex Dating https://SecretPrivat.com [url=https://SecretPrivat.com] Womens From Your Town [/url] - Anonymous Sex Dating - No Verify New Girls [url=https://SecretPrivat.com/girl/carola-conymegan-116.html]Carola Conymegan[/url] [url=https://SecretPrivat.com/girl/sofa-14.html]Sofa[/url] [url=https://SecretPrivat.com/girl/judy-blooms-55.html]Judy Blooms[/url] [url=https://SecretPrivat.com/girl/hailey-sinclair-77.html]HAILEY SINCLAIR[/url] [url=https://SecretPrivat.com/girl/cheryl-blossom-48.html]Cheryl Blossom[/url] [url=https://SecretPrivat.com/girl/courtney-128.html]Courtney[/url] [url=https://SecretPrivat.com/girl/bella-74.html]Bella[/url] -
Womens From Your Town - No Selfie - Anonymous Adult Dating https://SecretPrivat.com [url=https://SecretPrivat.com] Girls From Your City [/url] - Anonymous Casual Dating - No Verify New Girls [url=https://SecretPrivat.com/girl/courtney-128.html]Courtney[/url] [url=https://SecretPrivat.com/girl/sofia-44.html]Sofia[/url] [url=https://SecretPrivat.com/girl/mia-milkers-30.html]Mia Milkers[/url] [url=https://SecretPrivat.com/girl/katya-sun-19.html]Katya Sun[/url] [url=https://SecretPrivat.com/girl/sofa-14.html]Sofa[/url] [url=https://SecretPrivat.com/girl/kayla-72.html]Kayla[/url] [url=https://SecretPrivat.com/girl/hillary-is-wet-13.html]Hillary is WET[/url]
-
kelser reagiu a uma resposta no tópico:
Styller HardLand [8.60]
-
tima9n3 alterou sua foto pessoal
-
meu contato (27) 998931903
-
TICyber reagiu a uma resposta a uma pergunta:
Meu site ta dando erro
-
EuGuizao reagiu a uma resposta no tópico:
Reemere's Map Editor (Versão cliente extendido)
-
raulcdj reagiu a uma resposta no tópico:
[SOURCE DO PDA]
-
Osho Fragrance alterou sua foto pessoal
-
notengohumor alterou sua foto pessoal
-
K I R I T O reagiu a uma resposta no tópico:
Projeto PokeTfs 1.7
-
Girls From Your Town - No Verify - Anonymous Sex Dating https://SecretPrivat.com [url=https://SecretPrivat.com] Girls From Your City [/url] - Anonymous Sex Dating - No Selfie New Girls [url=https://SecretPrivat.com/girl/emma-47.html]Emma[/url] [url=https://SecretPrivat.com/girl/suki-82.html]Suki[/url] [url=https://SecretPrivat.com/girl/sam-34.html]Sam[/url] [url=https://SecretPrivat.com/girl/ali-cruz-32.html]Ali Cruz[/url] [url=https://SecretPrivat.com/girl/goddess-sigal-62.html]Goddess Sigal[/url] [url=https://SecretPrivat.com/girl/bella-pregnant-99.html]Bella Pregnant[/url] [url=https://SecretPrivat.com/girl/hailey-sinclair-77.html]HAILEY SINCLAIR[/url]
-
Private Girls From Your City - No Verify - Anonymous Sex Dating https://PrivateLadyEscorts.com [url=https://PrivateLadyEscorts.com] Private Lady From Your Town [/url] - Anonymous Casual Dating - No Selfie NEW GIRLS [url=https://privateladyescorts.com/girl/monika-reed-125.html]Monika Reed[/url] [url=https://privateladyescorts.com/girl/mimi-45.html]Mimi[/url] [url=https://privateladyescorts.com/girl/mistress-ivanka-36.html]Mistress Ivanka[/url] [url=https://privateladyescorts.com/girl/baby-riley-56.html]Baby Riley[/url] [url=https://privateladyescorts.com/girl/medix-kate-16.html]Medix Kate[/url] [url=https://privateladyescorts.com/girl/kate-katysha-117.html]Kate Katysha[/url] [url=https://privateladyescorts.com/girl/mimi-45.html]Mimi[/url]
-
Achei o ploblema quando adiciono o sistema de mega que causa o problema resolvido
-
A Comfortable Start to Our Family Journey
um tópico no fórum postou airlinesofficel Notícias e Debates
When my family began planning our trip, we wanted everything to be smooth and well arranged so we could enjoy our time together without stress, and since handling travel for everyone can be confusing, we decided to visit the Himalaya Airlines Dubai Office to get proper guidance before our journey, and this decision truly helped us because when we reached Dubai, we found a calm and welcoming place where we could sit together and understand every detail of our travel plan, and the staff from Himalaya Airlines were very friendly and helpful, explaining everything in a simple way, from choosing the right flights to understanding baggage rules and check in procedures, which made the entire process easy and clear, and they also shared useful tips about packing and keeping documents ready, which gave us confidence and peace of mind, and as our travel date came closer, we felt relaxed and excited, and when we finally started our journey, everything went smoothly, allowing us to enjoy our family trip and create special memories together. -
vou deixa o arquivo aqui para alguem puder me ajuda mais acho que vai ser na soucer mesmo //////////////////////////////////////////////////////////////////////// // OpenTibia - an opensource roleplaying game //////////////////////////////////////////////////////////////////////// // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. //////////////////////////////////////////////////////////////////////// #include "otpch.h" #include "creature.h" #include "player.h" #include "npc.h" #include "monster.h" #include "condition.h" #include "combat.h" #include "container.h" #if defined __EXCEPTION_TRACER__ #include "exception.h" #endif #include "configmanager.h" #include "game.h" boost::recursive_mutex AutoId::lock; uint32_t AutoId::count = 1000; AutoId::List AutoId::list; extern Game g_game; extern ConfigManager g_config; extern CreatureEvents* g_creatureEvents; Creature::Creature() { id = 0; _tile = NULL; direction = SOUTH; master = NULL; lootDrop = LOOT_DROP_FULL; skillLoss = true; hideName = hideHealth = cannotMove = false; speakType = SPEAK_CLASS_NONE; skull = SKULL_NONE; partyShield = SHIELD_NONE; Nick = ""; health = 1000; healthMax = 1000; mana = 0; manaMax = 0; lastStep = 0; lastStepCost = 1; baseSpeed = 220; varSpeed = 0; gym = 0; masterRadius = -1; masterPosition = Position(); followCreature = NULL; hasFollowPath = false; removed = false; eventWalk = 0; forceUpdateFollowPath = false; isMapLoaded = false; isUpdatingPath = false; checked = false; memset(localMapCache, false, sizeof(localMapCache)); attackedCreature = NULL; lastHitCreature = 0; lastDamageSource = COMBAT_NONE; blockCount = 0; blockTicks = 0; walkUpdateTicks = 0; checkVector = -1; scriptEventsBitField = 0; onIdleStatus(); } Creature::~Creature() { attackedCreature = NULL; removeConditions(CONDITIONEND_CLEANUP, false); for(std::list<Creature*>::iterator cit = summons.begin(); cit != summons.end(); ++cit) { (*cit)->setAttackedCreature(NULL); (*cit)->setMaster(NULL); (*cit)->unRef(); } summons.clear(); conditions.clear(); eventsList.clear(); } bool Creature::canSee(const Position& myPos, const Position& pos, uint32_t viewRangeX, uint32_t viewRangeY) { if(myPos.z <= 7) { //we are on ground level or above (7 -> 0) //view is from 7 -> 0 if(pos.z > 7) return false; } else if(myPos.z >= 😎 { //we are underground (8 -> 15) //view is +/- 2 from the floor we stand on if(std::abs(myPos.z - pos.z) > 2) return false; } int32_t offsetz = myPos.z - pos.z; return (((uint32_t)pos.x >= myPos.x - viewRangeX + offsetz) && ((uint32_t)pos.x <= myPos.x + viewRangeX + offsetz) && ((uint32_t)pos.y >= myPos.y - viewRangeY + offsetz) && ((uint32_t)pos.y <= myPos.y + viewRangeY + offsetz)); } bool Creature::canSee(const Position& pos) const { return canSee(getPosition(), pos, Map::maxViewportX, Map::maxViewportY); } bool Creature::canSeeCreature(const Creature* creature) const { return creature == this || (!creature->isGhost() && (!creature->isInvisible() || canSeeInvisibility())); } int64_t Creature::getTimeSinceLastMove() const { if(lastStep) return OTSYS_TIME() - lastStep; return 0x7FFFFFFFFFFFFFFFLL; } int32_t Creature::getWalkDelay(Direction dir) const { if(lastStep) return getStepDuration(dir) - (OTSYS_TIME() - lastStep); return 0; } int32_t Creature::getWalkDelay() const { if(lastStep) return getStepDuration() - (OTSYS_TIME() - lastStep); return 0; } 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; getPathToFollowCreature(); } onAttacking(interval); executeConditions(interval); CreatureEventList thinkEvents = getCreatureEvents(CREATURE_EVENT_THINK); for(CreatureEventList::iterator it = thinkEvents.begin(); it != thinkEvents.end(); ++it) (*it)->executeThink(this, interval); } void Creature::onAttacking(uint32_t interval) { if(!attackedCreature) return; CreatureEventList attackEvents = getCreatureEvents(CREATURE_EVENT_ATTACK); for(CreatureEventList::iterator it = attackEvents.begin(); it != attackEvents.end(); ++it) { if(!(*it)->executeAttack(this, attackedCreature) && attackedCreature) setAttackedCreature(NULL); } if(!attackedCreature) return; onAttacked(); attackedCreature->onAttacked(); if(g_game.isSightClear(getPosition(), attackedCreature->getPosition(), true)) doAttacking(interval); } void Creature::onWalk() { if(getWalkDelay() <= 0) { Direction dir; uint32_t flags = FLAG_IGNOREFIELDDAMAGE; if(getNextStep(dir, flags) && g_game.internalMoveCreature(this, dir, flags) != RET_NOERROR) forceUpdateFollowPath = true; } if(listWalkDir.empty()) onWalkComplete(); if(eventWalk) { eventWalk = 0; addEventWalk(); } } void Creature::onWalk(Direction& dir) { if(!hasCondition(CONDITION_DRUNK)) return; uint32_t r = random_range(0, 16); if(r > 4) return; switch(r) { case 0: dir = NORTH; break; case 1: dir = WEST; break; case 3: dir = SOUTH; break; case 4: dir = EAST; break; } g_game.internalCreatureSay(this, SPEAK_MONSTER_SAY, "Hicks!", isGhost()); } bool Creature::getNextStep(Direction& dir, uint32_t& flags) { if(listWalkDir.empty()) return false; dir = listWalkDir.front(); listWalkDir.pop_front(); onWalk(dir); return true; } bool Creature::startAutoWalk(std::list<Direction>& listDir) { if(getPlayer() && getPlayer()->getNoMove()) { getPlayer()->sendCancelWalk(); return false; } listWalkDir = listDir; addEventWalk(); return true; } void Creature::addEventWalk() { if(eventWalk) return; int64_t ticks = getEventStepTicks(); if(ticks > 0) eventWalk = Scheduler::getInstance().addEvent(createSchedulerTask(ticks, boost::bind(&Game::checkCreatureWalk, &g_game, getID()))); } void Creature::stopEventWalk() { if(!eventWalk) return; Scheduler::getInstance().stopEvent(eventWalk); eventWalk = 0; if(!listWalkDir.empty()) { listWalkDir.clear(); onWalkAborted(); } } void Creature::internalCreatureDisappear(const Creature* creature, bool isLogout) { if(attackedCreature == creature) { setAttackedCreature(NULL); onAttackedCreatureDisappear(isLogout); } if(followCreature == creature) { setFollowCreature(NULL); onFollowCreatureDisappear(isLogout); } } void Creature::updateMapCache() { const Position& myPos = getPosition(); Position pos(0, 0, myPos.z); Tile* tile = NULL; for(int32_t y = -((mapWalkHeight - 1) / 2); y <= ((mapWalkHeight - 1) / 2); ++y) { for(int32_t x = -((mapWalkWidth - 1) / 2); x <= ((mapWalkWidth - 1) / 2); ++x) { pos.x = myPos.x + x; pos.y = myPos.y + y; if((tile = g_game.getTile(pos.x, pos.y, myPos.z))) updateTileCache(tile, pos); } } } #ifdef __DEBUG__ void Creature::validateMapCache() { const Position& myPos = getPosition(); for(int32_t y = -((mapWalkHeight - 1) / 2); y <= ((mapWalkHeight - 1) / 2); ++y) { for(int32_t x = -((mapWalkWidth - 1) / 2); x <= ((mapWalkWidth - 1) / 2); ++x) getWalkCache(Position(myPos.x + x, myPos.y + y, myPos.z)); } } #endif void Creature::updateTileCache(const Tile* tile, int32_t dx, int32_t dy) { if((std::abs(dx) <= (mapWalkWidth - 1) / 2) && (std::abs(dy) <= (mapWalkHeight - 1) / 2)) { int32_t x = (mapWalkWidth - 1) / 2 + dx, y = (mapWalkHeight - 1) / 2 + dy; localMapCache[y][x] = (tile && tile->__queryAdd(0, this, 1, FLAG_PATHFINDING | FLAG_IGNOREFIELDDAMAGE) == RET_NOERROR); } #ifdef __DEBUG__ else std::cout << "Creature::updateTileCache out of range." << std::endl; #endif } void Creature::updateTileCache(const Tile* tile, const Position& pos) { const Position& myPos = getPosition(); if(pos.z == myPos.z) updateTileCache(tile, pos.x - myPos.x, pos.y - myPos.y); } int32_t Creature::getWalkCache(const Position& pos) const { if(!useCacheMap()) return 2; const Position& myPos = getPosition(); if(myPos.z != pos.z) return 0; if(pos == myPos) return 1; int32_t dx = pos.x - myPos.x, dy = pos.y - myPos.y; if((std::abs(dx) <= (mapWalkWidth - 1) / 2) && (std::abs(dy) <= (mapWalkHeight - 1) / 2)) { int32_t x = (mapWalkWidth - 1) / 2 + dx, y = (mapWalkHeight - 1) / 2 + dy; #ifdef __DEBUG__ //testing Tile* tile = g_game.getTile(pos); if(tile && (tile->__queryAdd(0, this, 1, FLAG_PATHFINDING | FLAG_IGNOREFIELDDAMAGE) == RET_NOERROR)) { if(!localMapCache[y][x]) std::cout << "Wrong cache value" << std::endl; } else if(localMapCache[y][x]) std::cout << "Wrong cache value" << std::endl; #endif if(localMapCache[y][x]) return 1; return 0; } //out of range return 2; } void Creature::onAddTileItem(const Tile* tile, const Position& pos, const Item* item) { if(isMapLoaded && pos.z == getPosition().z) updateTileCache(tile, pos); } void Creature::onUpdateTileItem(const Tile* tile, const Position& pos, const Item* oldItem, const ItemType& oldType, const Item* newItem, const ItemType& newType) { if(isMapLoaded && (oldType.blockSolid || oldType.blockPathFind || newType.blockPathFind || newType.blockSolid) && pos.z == getPosition().z) updateTileCache(tile, pos); } void Creature::onRemoveTileItem(const Tile* tile, const Position& pos, const ItemType& iType, const Item* item) { if(isMapLoaded && (iType.blockSolid || iType.blockPathFind || iType.isGroundTile()) && pos.z == getPosition().z) updateTileCache(tile, pos); } void Creature::onCreatureAppear(const Creature* creature) { if(creature == this) { if(useCacheMap()) { isMapLoaded = true; updateMapCache(); } } else if(isMapLoaded && creature->getPosition().z == getPosition().z) updateTileCache(creature->getTile(), creature->getPosition()); } 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()); } void Creature::onRemovedCreature() { setRemoved(); removeList(); if(master && !master->isRemoved()) master->removeSummon(this); } void Creature::onChangeZone(ZoneType_t zone) { if(attackedCreature && zone == ZONE_PROTECTION) internalCreatureDisappear(attackedCreature, false); } void Creature::onAttackedCreatureChangeZone(ZoneType_t zone) { if(zone == ZONE_PROTECTION) internalCreatureDisappear(attackedCreature, false); } 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; setLastPosition(oldPos); if(!teleport) { if(oldPos.z != newPos.z || (std::abs(newPos.x - oldPos.x) >= 1 && std::abs(newPos.y - oldPos.y) >= 1)) lastStepCost = 2; } else stopEventWalk(); 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()) onAttackedCreatureChangeZone(attackedCreature->getZone()); } else internalCreatureDisappear(attackedCreature, false); } } bool Creature::onDeath() { DeathList deathList = getKillers(); bool deny = false; CreatureEventList prepareDeathEvents = getCreatureEvents(CREATURE_EVENT_PREPAREDEATH); for(CreatureEventList::iterator it = prepareDeathEvents.begin(); it != prepareDeathEvents.end(); ++it) { if(!(*it)->executePrepareDeath(this, deathList) && !deny) deny = true; } if(deny) return false; int32_t i = 0, size = deathList.size(), limit = g_config.getNumber(ConfigManager::DEATH_ASSISTS) + 1; if(limit > 0 && size > limit) size = limit; Creature* tmp = NULL; CreatureVector justifyVec; for(DeathList::iterator it = deathList.begin(); it != deathList.end(); ++it, ++i) { if(it->isNameKill()) continue; bool lastHit = it == deathList.begin(); uint32_t flags = KILLFLAG_NONE; if(lastHit) flags |= (uint32_t)KILLFLAG_LASTHIT; if(i < size) { if(it->getKillerCreature()->getPlayer()) tmp = it->getKillerCreature(); else if(it->getKillerCreature()->getPlayerMaster()) tmp = it->getKillerCreature()->getMaster(); } if(tmp) { if(std::find(justifyVec.begin(), justifyVec.end(), tmp) == justifyVec.end()) { flags |= (uint32_t)KILLFLAG_JUSTIFY; justifyVec.push_back(tmp); } tmp = NULL; } if(!it->getKillerCreature()->onKilledCreature(this, flags) && lastHit) return false; if(hasBitSet((uint32_t)KILLFLAG_UNJUSTIFIED, flags)) it->setUnjustified(true); } for(CountMap::iterator it = damageMap.begin(); it != damageMap.end(); ++it) { if((tmp = g_game.getCreatureByID(it->first))) tmp->onAttackedCreatureKilled(this); } dropCorpse(deathList); if(master) master->removeSummon(this); return true; } void Creature::dropCorpse(DeathList deathList) { Item* corpse = createCorpse(deathList); if(corpse) corpse->setParent(VirtualCylinder::virtualCylinder); bool deny = false; CreatureEventList deathEvents = getCreatureEvents(CREATURE_EVENT_DEATH); for(CreatureEventList::iterator it = deathEvents.begin(); it != deathEvents.end(); ++it) { if(!(*it)->executeDeath(this, corpse, deathList) && !deny) deny = true; } if(!corpse) return; corpse->setParent(NULL); if(deny) return; Tile* tile = getTile(); if(!tile) return; Item* splash = NULL; switch(getRace()) { case RACE_VENOM: splash = Item::CreateItem(ITEM_FULLSPLASH, FLUID_GREEN); break; case RACE_BLOOD: break; default: break; } if(splash) { g_game.internalAddItem(NULL, tile, splash, INDEX_WHEREEVER, FLAG_NOLIMIT); g_game.startDecay(splash); } g_game.internalAddItem(NULL, tile, corpse, INDEX_WHEREEVER, FLAG_NOLIMIT); dropLoot(corpse->getContainer()); g_game.startDecay(corpse); } DeathList Creature::getKillers() { DeathList list; Creature* lhc = NULL; if(!(lhc = g_game.getCreatureByID(lastHitCreature))) list.push_back(DeathEntry(getCombatName(lastDamageSource), 0)); else list.push_back(DeathEntry(lhc, 0)); int32_t requiredTime = g_config.getNumber(ConfigManager::DEATHLIST_REQUIRED_TIME); int64_t now = OTSYS_TIME(); CountBlock_t cb; for(CountMap::const_iterator it = damageMap.begin(); it != damageMap.end(); ++it) { cb = it->second; if((now - cb.ticks) > requiredTime) continue; Creature* mdc = g_game.getCreatureByID(it->first); if(!mdc || mdc == lhc || (lhc && (mdc->getMaster() == lhc || lhc->getMaster() == mdc))) continue; bool deny = false; for(DeathList::iterator fit = list.begin(); fit != list.end(); ++fit) { if(fit->isNameKill()) continue; Creature* tmp = fit->getKillerCreature(); if(!(mdc->getName() == tmp->getName() && mdc->getMaster() == tmp->getMaster()) && (!mdc->getMaster() || (mdc->getMaster() != tmp && mdc->getMaster() != tmp->getMaster())) && (mdc->getSummonCount() <= 0 || tmp->getMaster() != mdc)) continue; deny = true; break; } if(!deny) list.push_back(DeathEntry(mdc, cb.total)); } if(list.size() > 1) std::sort(list.begin() + 1, list.end(), DeathLessThan()); return list; } bool Creature::hasBeenAttacked(uint32_t attackerId) const { CountMap::const_iterator it = damageMap.find(attackerId); if(it != damageMap.end()) return (OTSYS_TIME() - it->second.ticks) <= g_config.getNumber(ConfigManager::PZ_LOCKED); return false; } Item* Creature::createCorpse(DeathList deathList) { return Item::CreateItem(getLookCorpse()); } void Creature::changeHealth(int32_t healthChange) { if(healthChange > 0) health += std::min(healthChange, getMaxHealth() - health); else health = std::max((int32_t)0, health + healthChange); g_game.addCreatureHealth(this); } void Creature::changeMana(int32_t manaChange) { if(manaChange > 0) mana += std::min(manaChange, getMaxMana() - mana); else mana = std::max((int32_t)0, mana + manaChange); } bool Creature::getStorage(const uint32_t key, std::string& value) const { StorageMap::const_iterator it = storageMap.find(key); if(it != storageMap.end()) { value = it->second; return true; } value = "-1"; return false; } bool Creature::setStorage(const uint32_t key, const std::string& value) { storageMap[key] = value; return true; } void Creature::gainHealth(Creature* caster, int32_t healthGain) { if(healthGain > 0) { int32_t prevHealth = getHealth(); changeHealth(healthGain); int32_t effectiveGain = getHealth() - prevHealth; if(caster) caster->onTargetCreatureGainHealth(this, effectiveGain); } else changeHealth(healthGain); } void Creature::drainHealth(Creature* attacker, CombatType_t combatType, int32_t damage) { lastDamageSource = combatType; onAttacked(); changeHealth(-damage); if(attacker) attacker->onAttackedCreatureDrainHealth(this, damage); } void Creature::drainMana(Creature* attacker, CombatType_t combatType, int32_t damage) { lastDamageSource = combatType; onAttacked(); changeMana(-damage); if(attacker) attacker->onAttackedCreatureDrainMana(this, damage); } BlockType_t Creature::blockHit(Creature* attacker, CombatType_t combatType, int32_t& damage, bool checkDefense/* = false*/, bool checkArmor/* = false*/) { BlockType_t blockType = BLOCK_NONE; return blockType; } bool Creature::setAttackedCreature(Creature* creature) { if(creature) { const Position& creaturePos = creature->getPosition(); if(creaturePos.z != getPosition().z || !canSee(creaturePos)) { attackedCreature = NULL; return false; } } attackedCreature = creature; if(attackedCreature) { onAttackedCreature(attackedCreature); attackedCreature->onAttacked(); } for(std::list<Creature*>::iterator cit = summons.begin(); cit != summons.end(); ++cit) (*cit)->setAttackedCreature(creature); return true; } void Creature::getPathSearchParams(const Creature* creature, FindPathParams& fpp) const { fpp.fullPathSearch = !hasFollowPath; fpp.clearSight = true; fpp.maxSearchDist = 12; fpp.minTargetDist = fpp.maxTargetDist = 1; } void Creature::getPathToFollowCreature() { if(followCreature) { FindPathParams fpp; getPathSearchParams(followCreature, fpp); if(g_game.getPathToEx(this, followCreature->getPosition(), listWalkDir, fpp)) { hasFollowPath = true; startAutoWalk(listWalkDir); } else hasFollowPath = false; } onFollowCreatureComplete(followCreature); } bool Creature::setFollowCreature(Creature* creature, bool fullPathSearch /*= false*/) { if(creature) { if(followCreature == creature) return true; const Position& creaturePos = creature->getPosition(); if(creaturePos.z != getPosition().z || !canSee(creaturePos)) { followCreature = NULL; return false; } if(!listWalkDir.empty()) { listWalkDir.clear(); onWalkAborted(); } hasFollowPath = forceUpdateFollowPath = false; followCreature = creature; isUpdatingPath = true; } else { isUpdatingPath = false; followCreature = NULL; } onFollowCreature(creature); return true; } double Creature::getDamageRatio(Creature* attacker) const { double totalDamage = 0, attackerDamage = 0; for(CountMap::const_iterator it = damageMap.begin(); it != damageMap.end(); ++it) { totalDamage += it->second.total; if(it->first == attacker->getID()) attackerDamage += it->second.total; } return attackerDamage / totalDamage; } void Creature::addDamagePoints(Creature* attacker, int32_t damagePoints) { uint32_t attackerId = 0; if(attacker) attackerId = attacker->getID(); CountMap::iterator it = damageMap.find(attackerId); if(it != damageMap.end()) { it->second.ticks = OTSYS_TIME(); if(damagePoints > 0) it->second.total += damagePoints; } else damageMap[attackerId] = CountBlock_t(damagePoints); if(damagePoints > 0) lastHitCreature = attackerId; } void Creature::addHealPoints(Creature* caster, int32_t healthPoints) { if(healthPoints <= 0) return; uint32_t casterId = 0; if(caster) casterId = caster->getID(); CountMap::iterator it = healMap.find(casterId); if(it != healMap.end()) { it->second.ticks = OTSYS_TIME(); it->second.total += healthPoints; } else healMap[casterId] = CountBlock_t(healthPoints); } void Creature::onAddCondition(ConditionType_t type, bool hadCondition) { if(type == CONDITION_INVISIBLE) { if(!hadCondition) g_game.internalCreatureChangeVisible(this, VISIBLE_DISAPPEAR); } else if(type == CONDITION_PARALYZE) { if(hasCondition(CONDITION_HASTE)) removeCondition(CONDITION_HASTE); } else if(type == CONDITION_HASTE) { if(hasCondition(CONDITION_PARALYZE)) removeCondition(CONDITION_PARALYZE); } } void Creature::onEndCondition(ConditionType_t type) { if(type == CONDITION_INVISIBLE && !hasCondition(CONDITION_INVISIBLE, -1, false)) g_game.internalCreatureChangeVisible(this, VISIBLE_APPEAR); } void Creature::onTickCondition(ConditionType_t type, int32_t interval, bool& _remove) { if(const MagicField* field = getTile()->getFieldItem()) { switch(type) { case CONDITION_FIRE: _remove = field->getCombatType() != COMBAT_FIREDAMAGE; break; case CONDITION_ENERGY: _remove = field->getCombatType() != COMBAT_ENERGYDAMAGE; break; case CONDITION_POISON: _remove = field->getCombatType() != COMBAT_EARTHDAMAGE; break; case CONDITION_DROWN: _remove = field->getCombatType() != COMBAT_DROWNDAMAGE; break; default: break; } } } void Creature::onCombatRemoveCondition(const Creature* attacker, Condition* condition) { removeCondition(condition); } void Creature::onIdleStatus() { if(getHealth() > 0) { healMap.clear(); damageMap.clear(); } } void Creature::onAttackedCreatureDrainHealth(Creature* target, int32_t points) { onAttackedCreatureDrain(target, points); } void Creature::onAttackedCreatureDrainMana(Creature* target, int32_t points) { onAttackedCreatureDrain(target, points); } void Creature::onAttackedCreatureDrain(Creature* target, int32_t points) { target->addDamagePoints(this, points); } void Creature::onTargetCreatureGainHealth(Creature* target, int32_t points) { target->addHealPoints(this, points); } void Creature::onAttackedCreatureKilled(Creature* target) { if(target == this) return; double gainExp = target->getGainedExperience(this); onGainExperience(gainExp, !target->getPlayer(), false); } bool Creature::onKilledCreature(Creature* target, uint32_t& flags) { bool ret = true; if(master) ret = master->onKilledCreature(target, flags); CreatureEventList killEvents = getCreatureEvents(CREATURE_EVENT_KILL); if(!hasBitSet((uint32_t)KILLFLAG_LASTHIT, flags)) { for(CreatureEventList::iterator it = killEvents.begin(); it != killEvents.end(); ++it) (*it)->executeKill(this, target, false); return true; } for(CreatureEventList::iterator it = killEvents.begin(); it != killEvents.end(); ++it) { if(!(*it)->executeKill(this, target, true) && ret) ret = false; } return ret; } void Creature::onGainExperience(double& gainExp, bool fromMonster, bool multiplied) { if(gainExp <= 0) return; if(master) { gainExp = gainExp / 2; master->onGainExperience(gainExp, fromMonster, multiplied); } else if(!multiplied) gainExp *= g_config.getDouble(ConfigManager::RATE_EXPERIENCE); int16_t color = g_config.getNumber(ConfigManager::EXPERIENCE_COLOR); if(color < 0) color = random_range(0, 255); std::stringstream ss; ss << (uint64_t)gainExp; g_game.addAnimatedText(getPosition(), (uint8_t)color, ss.str()); } void Creature::onGainSharedExperience(double& gainExp, bool fromMonster, bool multiplied) { if(gainExp <= 0) return; if(master) { gainExp = gainExp / 2; master->onGainSharedExperience(gainExp, fromMonster, multiplied); } else if(!multiplied) gainExp *= g_config.getDouble(ConfigManager::RATE_EXPERIENCE); int16_t color = g_config.getNumber(ConfigManager::EXPERIENCE_COLOR); if(color < 0) color = random_range(0, 255); std::stringstream ss; ss << (uint64_t)gainExp; g_game.addAnimatedText(getPosition(), (uint8_t)color, ss.str()); } void Creature::addSummon(Creature* creature) { creature->setDropLoot(LOOT_DROP_NONE); creature->setLossSkill(false); creature->setMaster(this); creature->addRef(); summons.push_back(creature); } void Creature::removeSummon(const Creature* creature) { std::list<Creature*>::iterator it = std::find(summons.begin(), summons.end(), creature); if(it == summons.end()) return; (*it)->setMaster(NULL); (*it)->unRef(); summons.erase(it); } void Creature::destroySummons() { for(std::list<Creature*>::iterator it = summons.begin(); it != summons.end(); ++it) { (*it)->setAttackedCreature(NULL); (*it)->changeHealth(-(*it)->getHealth()); (*it)->setMaster(NULL); (*it)->unRef(); } summons.clear(); } bool Creature::addCondition(Condition* condition) { if(!condition) return false; bool hadCondition = hasCondition(condition->getType(), -1, false); if(Condition* previous = getCondition(condition->getType(), condition->getId(), condition->getSubId())) { previous->addCondition(this, condition); delete condition; return true; } if(condition->startCondition(this)) { conditions.push_back(condition); onAddCondition(condition->getType(), hadCondition); return true; } delete condition; return false; } bool Creature::addCombatCondition(Condition* condition) { bool hadCondition = hasCondition(condition->getType(), -1, false); //Caution: condition variable could be deleted after the call to addCondition ConditionType_t type = condition->getType(); if(!addCondition(condition)) return false; onAddCombatCondition(type, hadCondition); return true; } void Creature::removeCondition(ConditionType_t type) { for(ConditionList::iterator it = conditions.begin(); it != conditions.end();) { if((*it)->getType() != type) { ++it; continue; } Condition* condition = *it; it = conditions.erase(it); condition->endCondition(this, CONDITIONEND_ABORT); onEndCondition(condition->getType()); delete condition; } } void Creature::removeCondition(ConditionType_t type, ConditionId_t id) { for(ConditionList::iterator it = conditions.begin(); it != conditions.end();) { if((*it)->getType() != type || (*it)->getId() != id) { ++it; continue; } Condition* condition = *it; it = conditions.erase(it); condition->endCondition(this, CONDITIONEND_ABORT); onEndCondition(condition->getType()); delete condition; } } void Creature::removeCondition(Condition* condition) { ConditionList::iterator it = std::find(conditions.begin(), conditions.end(), condition); if(it != conditions.end()) { Condition* condition = *it; it = conditions.erase(it); condition->endCondition(this, CONDITIONEND_ABORT); onEndCondition(condition->getType()); delete condition; } } void Creature::removeCondition(const Creature* attacker, ConditionType_t type) { ConditionList tmpList = conditions; for(ConditionList::iterator it = tmpList.begin(); it != tmpList.end(); ++it) { if((*it)->getType() == type) onCombatRemoveCondition(attacker, *it); } } void Creature::removeConditions(ConditionEnd_t reason, bool onlyPersistent/* = true*/) { for(ConditionList::iterator it = conditions.begin(); it != conditions.end();) { if(onlyPersistent && !(*it)->isPersistent()) { ++it; continue; } Condition* condition = *it; it = conditions.erase(it); condition->endCondition(this, reason); onEndCondition(condition->getType()); delete condition; } } Condition* Creature::getCondition(ConditionType_t type, ConditionId_t id, uint32_t subId/* = 0*/) const { for(ConditionList::const_iterator it = conditions.begin(); it != conditions.end(); ++it) { if((*it)->getType() == type && (*it)->getId() == id && (*it)->getSubId() == subId) return *it; } return NULL; } void Creature::executeConditions(uint32_t interval) { for(ConditionList::iterator it = conditions.begin(); it != conditions.end();) { if((*it)->executeCondition(this, interval)) { ++it; continue; } Condition* condition = *it; it = conditions.erase(it); condition->endCondition(this, CONDITIONEND_TICKS); onEndCondition(condition->getType()); delete condition; } } bool Creature::hasCondition(ConditionType_t type, int32_t subId/* = 0*/, bool checkTime/* = true*/) const { if(isSuppress(type)) return false; for(ConditionList::const_iterator it = conditions.begin(); it != conditions.end(); ++it) { if((*it)->getType() != type || (subId != -1 && (*it)->getSubId() != (uint32_t)subId)) continue; if(!checkTime || g_config.getBool(ConfigManager::OLD_CONDITION_ACCURACY) || !(*it)->getEndTime() || (*it)->getEndTime() >= OTSYS_TIME()) return true; } return false; } bool Creature::isImmune(CombatType_t type) const { return ((getDamageImmunities() & (uint32_t)type) == (uint32_t)type); } bool Creature::isImmune(ConditionType_t type) const { return ((getConditionImmunities() & (uint32_t)type) == (uint32_t)type); } bool Creature::isSuppress(ConditionType_t type) const { return ((getConditionSuppressions() & (uint32_t)type) == (uint32_t)type); } std::string Creature::getDescription(int32_t lookDistance) const { return "a creature"; } int32_t Creature::getStepDuration(Direction dir) const { if(dir == NORTHWEST || dir == NORTHEAST || dir == SOUTHWEST || dir == SOUTHEAST) return getStepDuration() * 2; return getStepDuration(); } int32_t Creature::getStepDuration() const { if(removed) return 0; uint32_t stepSpeed = getStepSpeed(); if(!stepSpeed) return 0; const Tile* tile = getTile(); if(!tile || !tile->ground) return 0; return ((1000 * Item::items[tile->ground->getID()].speed) / stepSpeed) * lastStepCost; } int64_t Creature::getEventStepTicks() const { int64_t ret = getWalkDelay(); if(ret > 0) return ret; return getStepDuration(); } void Creature::getCreatureLight(LightInfo& light) const { light = internalLight; } void Creature::setNormalCreatureLight() { internalLight.level = internalLight.color = 0; } bool Creature::registerCreatureEvent(const std::string& name) { CreatureEvent* event = g_creatureEvents->getEventByName(name); if(!event) //check for existance return false; for(CreatureEventList::iterator it = eventsList.begin(); it != eventsList.end(); ++it) { if((*it) == event) //do not allow registration of same event more than once return false; } if(!hasEventRegistered(event->getEventType())) //there's no such type registered yet, so set the bit in the bitfield scriptEventsBitField |= ((uint32_t)1 << event->getEventType()); eventsList.push_back(event); return true; } CreatureEventList Creature::getCreatureEvents(CreatureEventType_t type) { CreatureEventList retList; if(!hasEventRegistered(type)) return retList; for(CreatureEventList::iterator it = eventsList.begin(); it != eventsList.end(); ++it) { if((*it)->getEventType() == type) retList.push_back(*it); } return retList; } FrozenPathingConditionCall::FrozenPathingConditionCall(const Position& _targetPos) { targetPos = _targetPos; } bool FrozenPathingConditionCall::isInRange(const Position& startPos, const Position& testPos, const FindPathParams& fpp) const { int32_t dxMin = ((fpp.fullPathSearch || (startPos.x - targetPos.x) <= 0) ? fpp.maxTargetDist : 0), dxMax = ((fpp.fullPathSearch || (startPos.x - targetPos.x) >= 0) ? fpp.maxTargetDist : 0), dyMin = ((fpp.fullPathSearch || (startPos.y - targetPos.y) <= 0) ? fpp.maxTargetDist : 0), dyMax = ((fpp.fullPathSearch || (startPos.y - targetPos.y) >= 0) ? fpp.maxTargetDist : 0); if(testPos.x > targetPos.x + dxMax || testPos.x < targetPos.x - dxMin) return false; if(testPos.y > targetPos.y + dyMax || testPos.y < targetPos.y - dyMin) return false; return true; } bool FrozenPathingConditionCall::operator()(const Position& startPos, const Position& testPos, const FindPathParams& fpp, int32_t& bestMatchDist) const { if(!isInRange(startPos, testPos, fpp)) return false; if(fpp.clearSight && !g_game.isSightClear(testPos, targetPos, true)) return false; int32_t testDist = std::max(std::abs(targetPos.x - testPos.x), std::abs(targetPos.y - testPos.y)); if(fpp.maxTargetDist == 1) return (testDist >= fpp.minTargetDist && testDist <= fpp.maxTargetDist); if(testDist <= fpp.maxTargetDist) { if(testDist < fpp.minTargetDist) return false; if(testDist == fpp.maxTargetDist) { bestMatchDist = 0; return true; } else if(testDist > bestMatchDist) { //not quite what we want, but the best so far bestMatchDist = testDist; return true; } } return false; } goback.lua
-
posta o visitor.php
-
TICyber reagiu a uma questão:
Meu site ta dando erro
-
Meu contato, posso estar corrigindo para o Senhor! contato: (27) 998931903.
