// solar: causes caster to hit every mob within dist range of center with // spell_id. // NPC spells will only affect other NPCs with compatible faction void EntityList::AESpell(Mob *caster, Mob *center, uint16 spell_id, bool affect_caster, int16 resist_adjust) { LinkedListIterator<Mob*> iterator(mob_list); Mob *curmob; float dist = caster->GetAOERange(spell_id); float dist2 = dist * dist; bool bad = IsDetrimentalSpell(spell_id); bool isnpc = caster->IsNPC(); const int MAX_TARGETS_ALLOWED = 4; int iCounter = 0; for(iterator.Reset(); iterator.MoreElements(); iterator.Advance()) { curmob = iterator.GetData(); if(curmob == center) //do not affect center continue; if(curmob == caster && !affect_caster) //watch for caster too continue; if(center->DistNoRoot(*curmob) > dist2) //make sure they are in range continue; if(isnpc && curmob->IsNPC()) { //check npc->npc casting FACTION_VALUE f = curmob->GetReverseFactionCon(caster); if(bad) { //affect mobs that are on our hate list, or //which have bad faction with us if( ! (caster->CheckAggro(curmob) || f == FACTION_THREATENLY || f == FACTION_SCOWLS) ) continue; } else { //only affect mobs we would assist. if( ! (f <= FACTION_AMIABLE)) continue; } } //finally, make sure they are within range if(bad) { if(!caster->IsAttackAllowed(curmob, true)) continue; if(!center->CheckLosFN(curmob)) continue; } //if we get here... cast the spell. if(IsTargetableAESpell(spell_id) && bad) { if(iCounter < MAX_TARGETS_ALLOWED) { caster->SpellOnTarget(spell_id, curmob, false, true, resist_adjust); } } else { caster->SpellOnTarget(spell_id, curmob, false, true, resist_adjust); } if(!isnpc) //npcs are not target limited... iCounter++; } }
void Level::trySpawn(int count) { for (int i = 0; i < count; i++) { Mob * mob; int minLevel = 1; int maxLevel = 1; if (depth < 0) { maxLevel = (-depth) + 1; } if (depth > 0) { minLevel = maxLevel = 4; } int lvl = random->nextInt(maxLevel - minLevel + 1) + minLevel; if (random->nextInt(2) == 0) mob = new Slime(lvl); else mob = new Zombie(lvl); if (!mob->findStartPos(this)) { delete mob; } else { this->add(mob); } } }
int16 QuestManager::unique_spawn(int npc_type, int grid, int unused, float x, float y, float z, float heading) { Mob *other = entity_list.GetMobByNpcTypeID(npc_type); if(other != NULL) { return(other->GetID()); } NPCType* tmp = 0; if ((tmp = Database::Instance()->GetNPCType(npc_type))) { NPC* npc = new NPC(tmp, 0, x, y, z, heading); npc->AddLootTable(); entity_list.AddNPC(npc,true); // Quag: Sleep in main thread? ICK! // Sleep(200); // Quag: check is irrelevent, it's impossible for npc to be 0 here // (we're in main thread, nothing else can possibly modify it) // if(npc != 0) { if(grid > 0) { // HarakiriFIXME npc->AssignWaypoints(grid); } npc->SendPosUpdate(); // } return(npc->GetID()); } return(0); }
bool Trap::Process() { if (chkarea_timer.Enabled() && chkarea_timer.Check() && !reset_timer.Enabled()) { Mob* trigger = entity_list.GetTrapTrigger(this); if (trigger && !(trigger->IsClient() && trigger->CastToClient()->GetGM())) { Trigger(trigger); } } else if (reset_timer.Enabled() && reset_timer.Check()) { Log.Out(Logs::General, Logs::Traps, "Reset timer disabled in Reset Check Process for trap %d.", trap_id); reset_timer.Disable(); charid = 0; } if (respawn_timer.Enabled() && respawn_timer.Check()) { detected = false; disarmed = false; chkarea_timer.Enable(); respawn_timer.Disable(); } return true; }
void Group::ChangeLeader(Mob* newleader) { // this changes the current group leader, notifies other members, and updates leadship AA // if the new leader is invalid, do nothing if (!newleader) return; Mob* oldleader = GetLeader(); EQApplicationPacket* outapp = new EQApplicationPacket(OP_GroupUpdate,sizeof(GroupJoin_Struct)); GroupJoin_Struct* gu = (GroupJoin_Struct*) outapp->pBuffer; gu->action = groupActMakeLeader; strcpy(gu->membername, newleader->GetName()); strcpy(gu->yourname, oldleader->GetName()); SetLeader(newleader); database.SetGroupLeaderName(GetID(), newleader->GetName()); for (uint32 i = 0; i < MAX_GROUP_MEMBERS; i++) { if (members[i] && members[i]->IsClient()) { members[i]->CastToClient()->QueuePacket(outapp); } } safe_delete(outapp); }
void Game::UpdateLogic(float time) { // Updates all the game logic: one game turn has passed! // Clear the screen TCODConsole::root->setBackgroundFlag(TCOD_BKGND_SET); TCODConsole::root->setDefaultBackground(TCODColor::black); TCODConsole::root->setDefaultForeground(TCODColor::black); TCODConsole::root->clear(); // Get all the mobs to update std::vector<Mob*> AllMobs = GameMap.GetAllMobs(); for(int i = 0; i < AllMobs.size(); i++) { Mob* mob = AllMobs[i]; /* If entity is a mob and set to skip update; then skip this mob! */ if(Helper::Find(mob->groups, std::string("nologic"))) continue; mob->tenergy += mob->get_property<int>("speed"); // add some energy while(mob->tenergy >= time) { mob->tenergy -= 100.0f; // 100.0f would be one second I guess mob->DoLogic(this); } } /* Clean out the delete buffer */ if(DeleteBuff.size() >= 200) { delete(DeleteBuff[0]); DeleteBuff.erase( DeleteBuff.begin() ); } }
// Rampage and stuff for clients. Normal and Duration rampages //NPCs handle it differently in Mob::Rampage void EntityList::AEAttack(Mob *attacker, float dist, int Hand, int count, bool IsFromSpell) { //Dook- Will need tweaking, currently no pets or players or horses Mob *curmob; float dist2 = dist * dist; int hit = 0; for (auto it = mob_list.begin(); it != mob_list.end(); ++it) { curmob = it->second; if (curmob->IsNPC() && curmob != attacker //this is not needed unless NPCs can use this &&(attacker->IsAttackAllowed(curmob)) && curmob->GetRace() != 216 && curmob->GetRace() != 472 /* dont attack horses */ && (DistanceSquared(curmob->GetPosition(), attacker->GetPosition()) <= dist2) ) { if (!attacker->IsClient() || attacker->GetClass() == MONK || attacker->GetClass() == RANGER) attacker->Attack(curmob, Hand, false, false, IsFromSpell); else attacker->CastToClient()->DoAttackRounds(curmob, Hand, IsFromSpell); hit++; if (count != 0 && hit >= count) return; } } }
void Game::killBody() { if(m_bodyToKill) { m_world.removeBody(m_bodyToKill); for(unsigned int i=0;i<m_mobs.size();i++) { if(m_mobs[i]->entity() == m_bodyToKill) { Mob* mobToDelete = m_mobs[i]; for(unsigned int j=0;j<m_map.size();j++) { if(mobToDelete->drawable() == m_map[j]) { m_map.erase(m_map.begin()+j); break; } } m_mobs.erase(m_mobs.begin()+i); delete mobToDelete; break; } } m_bodyToKill = 0; } }
void MapMobs::sendmobhp(int32_t oid, int8_t percent, uint16_t playerlevel) { Mob* mob = getmob(oid); if (mob) { mob->sendhp(percent, playerlevel); } }
void MapMobs::killmob(int32_t oid, int8_t animation) { Mob* mob = getmob(oid); if (mob) { mob->kill(animation); } }
int mob_spawnMobN(const char* name) { int type = Mineserver::get()->mobs()->mobNametoType(std::string(name)); Mob* m = Mineserver::get()->mobs()->createMob(); m->type = type; m->spawnToAll(); m->teleportToAll(); return Mineserver::get()->mobs()->getAll().size()-1; }
void MobSpawner::spawnMob(RType::InGameEvent const& request) { MobObject *mob = _mobs->create("Mob", 12); mob->init(_mobTypes->at(request.get<uint8_t>("mob_id")).get()); _activeMobs.push_back(mob); Mob *m = mob->getComponent<Mob>(); m->setX(request.get<uint32_t>("x")); m->setY(request.get<uint32_t>("y")); }
void MapMobs::addmob(int32_t oid, int32_t id, bool control, int8_t stance, uint16_t fhid, int8_t effect, bool fadein, int8_t team, int16_t x, int16_t y) { Mob* mob = getmob(oid); if (mob) mob->makeactive(); else add(new Mob(oid, id, control, stance, fhid, effect, fadein, team, x, y)); }
void Client::ProcessMovePC(uint32 zoneID, uint32 instance_id, float x, float y, float z, float heading, uint8 ignorerestrictions, ZoneMode zm) { // From what I have read, dragged corpses should stay with the player for Intra-zone summons etc, but we can implement that later. ClearDraggedCorpses(); if(zoneID == 0) zoneID = zone->GetZoneID(); if(zoneID == zone->GetZoneID() && instance_id == zone->GetInstanceID()) { // TODO: Determine if this condition is necessary. if(IsAIControlled()) { GMMove(x, y, z); return; } if(GetPetID() != 0) { //if they have a pet and they are staying in zone, move with them Mob *p = GetPet(); if(p != nullptr){ p->SetPetOrder(SPO_Follow); p->GMMove(x+15, y, z); //so it dosent have to run across the map. } } } switch(zm) { case GateToBindPoint: ZonePC(zoneID, instance_id, x, y, z, heading, ignorerestrictions, zm); break; case EvacToSafeCoords: case ZoneToSafeCoords: ZonePC(zoneID, instance_id, x, y, z, heading, ignorerestrictions, zm); break; case GMSummon: Message(15, "You have been summoned by a GM!"); ZonePC(zoneID, instance_id, x, y, z, heading, ignorerestrictions, zm); break; case ZoneToBindPoint: ZonePC(zoneID, instance_id, x, y, z, heading, ignorerestrictions, zm); break; case ZoneSolicited: ZonePC(zoneID, instance_id, x, y, z, heading, ignorerestrictions, zm); break; case SummonPC: Message(15, "You have been summoned!"); ZonePC(zoneID, instance_id, x, y, z, heading, ignorerestrictions, zm); break; case Rewind: Message(15, "Rewinding to previous location."); ZonePC(zoneID, instance_id, x, y, z, heading, ignorerestrictions, zm); break; default: LogFile->write(EQEMuLog::Error, "Client::ProcessMovePC received a reguest to perform an unsupported client zone operation."); break; } }
void QuestManager::attacknpc(int npc_entity_id) { if(!owner->IsNPC()) return; Mob *it = entity_list.GetMob(npc_entity_id); owner->CastToNPC()->AddToHateList(it,1); if(it) owner->Say("I am unable to attack %s.", it->GetName()); else owner->Say("I am unable to locate NPC entity %i", npc_entity_id); }
bool mob_setLook(int uid, double rot, double pitch) { Mob* m = Mineserver::get()->mobs()->getMobByID(uid); if (m != NULL) { m->look((int16_t)rot, (int16_t)pitch); return true; } return false; }
void Mob::FadePetCharmBuff() { if ((this->GetPetType() == petCharmed)) { Mob* formerpet = this->GetPet(); if (formerpet) { formerpet->BuffFadeByEffect(SE_Charm); } } }
//look around a client for things which might aggro the client. void EntityList::CheckClientAggro(Client *around) { for (auto it = mob_list.begin(); it != mob_list.end(); ++it) { Mob *mob = it->second; if (mob->IsClient()) //also ensures that mob != around continue; if (mob->CheckWillAggro(around) && !mob->CheckAggro(around)) mob->AddToHateList(around, 25); } }
void MobHandler::handleBomb(Player *player, PacketReader &packet) { int32_t mobid = packet.get<int32_t>(); Mob *mob = Maps::getMap(player->getMap())->getMob(mobid); if (player->getStats()->getHp() == 0 || mob == nullptr) { return; } if (mob->getSelfDestructHp() == 0) { // Hacking, I think return; } mob->explode(); }
void TSimulator::simulate() { mobs->reset(); Mob* current = mobs->getItem(); while (current != NULL) { current->step(); mobs->next(); current = mobs->getItem(); } }
// solar: causes caster to hit every mob within dist range of center with // a bard pulse of spell_id. // NPC spells will only affect other NPCs with compatible faction void EntityList::AEBardPulse(Mob *caster, Mob *center, uint16 spell_id, bool affect_caster) { Mob *curmob; float dist = caster->GetAOERange(spell_id); float dist2 = dist * dist; bool bad = IsDetrimentalSpell(spell_id); bool isnpc = caster->IsNPC(); for (auto it = mob_list.begin(); it != mob_list.end(); ++it) { curmob = it->second; if (curmob == center) //do not affect center continue; if (curmob == caster && !affect_caster) //watch for caster too continue; if (DistanceSquared(center->GetPosition(), curmob->GetPosition()) > dist2) //make sure they are in range continue; if (isnpc && curmob->IsNPC()) { //check npc->npc casting FACTION_VALUE f = curmob->GetReverseFactionCon(caster); if (bad) { //affect mobs that are on our hate list, or //which have bad faction with us if (!(caster->CheckAggro(curmob) || f == FACTION_THREATENLY || f == FACTION_SCOWLS) ) continue; } else { //only affect mobs we would assist. if (!(f <= FACTION_AMIABLE)) continue; } } //finally, make sure they are within range if (bad) { if (!center->CheckLosFN(curmob)) continue; } else { // check to stop casting beneficial ae buffs (to wit: bard songs) on enemies... // See notes in AESpell() above for more info. if (caster->IsAttackAllowed(curmob, true)) continue; if (caster->CheckAggro(curmob)) continue; AddHealAggro(curmob, caster, caster->CheckHealAggroAmount(spell_id, curmob)); } //if we get here... cast the spell. curmob->BardPulse(spell_id, caster); } if (caster->IsClient()) caster->CastToClient()->CheckSongSkillIncrease(spell_id); }
void HateList::SpellCast(Mob *caster, uint32 spell_id, float range, Mob* ae_center) { if (!caster) return; Mob* center = caster; if (ae_center) center = ae_center; //this is slower than just iterating through the list but avoids //crashes when people kick the bucket in the middle of this call //that invalidates our iterator but there's no way to know sadly //So keep a list of entity ids and look up after std::list<uint32> id_list; range = range * range; float min_range2 = spells[spell_id].min_range * spells[spell_id].min_range; float dist_targ = 0; auto iterator = list.begin(); while (iterator != list.end()) { struct_HateList *h = (*iterator); if (range > 0) { dist_targ = DistanceSquared(center->GetPosition(), h->entity_on_hatelist->GetPosition()); if (dist_targ <= range && dist_targ >= min_range2) { id_list.push_back(h->entity_on_hatelist->GetID()); h->entity_on_hatelist->CalcSpellPowerDistanceMod(spell_id, dist_targ); } } else { id_list.push_back(h->entity_on_hatelist->GetID()); h->entity_on_hatelist->CalcSpellPowerDistanceMod(spell_id, 0, caster); } ++iterator; } std::list<uint32>::iterator iter = id_list.begin(); while (iter != id_list.end()) { Mob *cur = entity_list.GetMobID((*iter)); if (cur) { caster->SpellOnTarget(spell_id, cur); } iter++; } }
void Mob::SetPet(Mob* newpet) { Mob* oldpet = GetPet(); if (oldpet && IsClient()) { oldpet->SetOwnerID(0); } if (newpet == nullptr) { SetPetID(0); } else { SetPetID(newpet->GetID()); Mob* oldowner = entity_list.GetMob(newpet->GetOwnerID()); if (oldowner && oldowner->IsClient()) oldowner->SetPetID(0); newpet->SetOwnerID(this->GetID()); } }
void missile_explode(body* b, contactdetails* cd){ Missile* m = (Missile*)b->data; body* other; if (cd->b1 == b) other = cd->b2; else other = cd->b1; if (!(other->dataFlag&OKMISSILE)) return; if (other->dataFlag& MOB_FLAG){ Mob* mob = (Mob*)(other->data); mob->dmg(m->dmg); } m->life = -1; }
void HateList::Wipe() { LinkedListIterator<tHateEntry*> iterator(list); iterator.Reset(); while(iterator.MoreElements()) { Mob* m = iterator.GetData()->ent; parse->EventNPC(EVENT_HATE_LIST, owner->CastToNPC(), m, "0", 0); iterator.RemoveCurrent(); if(m->IsClient()) m->CastToClient()->DecrementAggroCount(); } }
void QuestManager::depopall(int npc_type) { if(owner->IsNPC() && npc_type > 0) { Mob* tmp = entity_list.GetMobByNpcTypeID(npc_type); while(tmp) { if(tmp != owner){ tmp->CastToNPC()->Depop(); entity_list.RemoveNPC(tmp->CastToNPC()); } else depop_npc = true; tmp = entity_list.GetMobByNpcTypeID(npc_type); } } }
Mob * MobManager::Create() { Mob *mob = GetOneMobFromBuffer(); if (mob) { UnitManager::GetMe()->AddUnit(mob); mob->SetType(Mobs); return mob; } else { // 有错误 return 0; } }
void Mob::SetPet(Mob* newpet) { Mob* oldpet = GetPet(); if (oldpet) { oldpet->SetOwnerID(0); } if (newpet == NULL) { SetPetID(0); } else { SetPetID(newpet->GetID()); Mob* oldowner = entity_list.GetMob(newpet->GetOwnerID()); if (oldowner) oldowner->SetPetID(0); newpet->SetOwnerID(this->GetID()); } }
void Client::SetHorseId(uint16 horseid_in) { //if its the same, do nothing if(horseId == horseid_in) return; //otherwise it changed. //if we have a horse, get rid of it no matter what. if(horseId) { Mob *horse = entity_list.GetMob(horseId); if(horse != nullptr) horse->Depop(); } //now we take whatever they gave us. horseId = horseid_in; }
void MobHandler::handleTurncoats(Player *player, PacketReader &packet) { int32_t mobfrom = packet.get<int32_t>(); int32_t playerid = packet.get<int32_t>(); int32_t mobto = packet.get<int32_t>(); packet.skipBytes(1); // Same as player damage, -1 = bump, integer = skill ID int32_t damage = packet.get<int32_t>(); packet.skipBytes(1); // Facing direction packet.skipBytes(4); // Some type of pos, damage display, I think Map *map = Maps::getMap(player->getMap()); Mob *damager = map->getMob(mobfrom); Mob *taker = map->getMob(mobto); if (damager != nullptr && taker != nullptr) { taker->applyDamage(playerid, damage); } }