void Item::LoadLootFromDB(Field *fields) { uint32 item_id = fields[1].GetUInt32(); uint32 item_amount = fields[2].GetUInt32(); uint32 item_suffix = fields[3].GetUInt32(); int32 item_propid = fields[4].GetInt32(); // money value special case if (item_id == 0) { loot.gold = item_amount; SetLootState(ITEM_LOOT_UNCHANGED); return; } // normal item case ItemPrototype const* proto = ObjectMgr::GetItemPrototype(item_id); if(!proto) { CharacterDatabase.PExecute("DELETE FROM item_loot WHERE guid = '%u' AND itemid = '%u'", GetGUIDLow(), item_id); sLog.outError("Item::LoadLootFromDB: %s has an unknown item (id: #%u) in item_loot, deleted.", GetOwnerGuid().GetString().c_str(), item_id); return; } loot.items.push_back(LootItem(item_id, item_amount, item_suffix, item_propid)); ++loot.unlootedCount; SetLootState(ITEM_LOOT_UNCHANGED); }
void Item::LoadLootFromDB(Field* fields) { uint32 itemId = fields[1].GetUInt32(); uint32 itemAmount = fields[2].GetUInt32(); // money value special case if (!itemId) { loot.gold = itemAmount; SetLootState(ITEM_LOOT_UNCHANGED); return; } // normal item case ItemPrototype const* proto = ObjectMgr::GetItemPrototype(itemId); if (!proto) { DeleteLootFromDB(GetGUIDLow(), itemId); sLog.outError("Item::LoadLootFromDB: %s has an unknown item (id: %u) in item_loot, deleted.", GetGuidStr().c_str(), itemId); return; } uint32 itemSuffix = fields[3].GetUInt32(); int32 itemPropId = fields[4].GetInt32(); loot.items.push_back(LootItem(itemId, itemAmount, itemSuffix, itemPropId)); ++loot.unlootedCount; SetLootState(ITEM_LOOT_UNCHANGED); }
void Item::LoadLootFromDB(Field* fields) { uint32 item_id = abs(fields[1].GetInt32()); uint8 type = fields[1].GetInt32() > 0 ? LOOT_ITEM_TYPE_ITEM : LOOT_ITEM_TYPE_CURRENCY; uint32 item_amount = fields[2].GetUInt32(); uint32 item_suffix = fields[3].GetUInt32(); int32 item_propid = fields[4].GetInt32(); // money value special case if (item_id == 0) { loot.gold = item_amount; SetLootState(ITEM_LOOT_UNCHANGED); return; } // normal item case if (type == LOOT_ITEM_TYPE_ITEM) { ItemPrototype const* proto = ObjectMgr::GetItemPrototype(item_id); if (!proto) { CharacterDatabase.PExecute("DELETE FROM item_loot WHERE guid = '%u' AND itemid = '%u'", GetGUIDLow(), item_id); sLog.outError("Item::LoadLootFromDB: %s has an unknown item (id: #%u) in item_loot, deleted.", GetOwnerGuid().GetString().c_str(), item_id); return; } loot.items.push_back(LootItem(item_id, type, item_amount, item_suffix, item_propid)); } // currency case else //if (type == LOOT_ITEM_TYPE_CURRENCY) { CurrencyTypesEntry const* currencyEntry = sCurrencyTypesStore.LookupEntry(item_id); if (!currencyEntry) { CharacterDatabase.PExecute("DELETE FROM item_loot WHERE guid = '%u' AND itemid = '%i'", GetGUIDLow(), -int32(item_id)); sLog.outError("Item::LoadLootFromDB: %s has an unknown currency (id: #%u) in item_loot, deleted.", GetOwnerGuid().GetString().c_str(), item_id); return; } loot.items.push_back(LootItem(item_id, type, item_amount)); } ++loot.unlootedCount; SetLootState(ITEM_LOOT_UNCHANGED); }
void GameObject::ResetDoorOrButton() { if (m_lootState == GO_READY || m_lootState == GO_JUST_DEACTIVATED) return; SwitchDoorOrButton(false); SetLootState(GO_JUST_DEACTIVATED); m_cooldownTime = 0; }
void MOTransport::Stop() { DETAIL_FILTER_LOG(LOG_FILTER_TRANSPORT_MOVES, "Transport::StartMovement %s (%s) stop moves, period %u/%u", GetObjectGuid().GetString().c_str(), GetName(), m_pathTime, GetPeriod() ); SetActiveObjectState(false); RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_IN_USE); SetGoState(GO_STATE_READY); SetLootState(GO_JUST_DEACTIVATED); }
void GameObject::UseDoorOrButton(uint32 time_to_restore, bool alternative /* = false */) { if(m_lootState != GO_READY) return; if(!time_to_restore) time_to_restore = GetGOInfo()->GetAutoCloseTime(); SwitchDoorOrButton(true,alternative); SetLootState(GO_ACTIVATED); m_cooldownTime = time(NULL) + time_to_restore; }
void GameObject::UseDoorOrButton(uint32 time_to_restore) { if(m_lootState != GO_READY) return; if(!time_to_restore) time_to_restore = GetAutoCloseTime(); SwitchDoorOrButton(true); SetLootState(GO_ACTIVATED); m_cooldownTime = time(NULL) + time_to_restore; }
void Item::SaveToDB() { uint32 guid = GetGUIDLow(); switch(m_state) { case ITEM_NEW: { DeleteFromDB(guid); std::ostringstream ss; for (uint16 i = 0; i < m_valuesCount; ++i) ss << GetUInt32Value(i) << " "; static SqlStatementID insItem; SqlStatement stmt = CharacterDatabase.CreateStatement(insItem, "INSERT INTO item_instance (guid, owner_guid, data, text) VALUES (?, ?, ?, ?)"); stmt.PExecute(guid, GetOwnerGuid().GetCounter(), ss.str().c_str(), m_text.c_str()); break; } case ITEM_CHANGED: { std::ostringstream ss; for (uint16 i = 0; i < m_valuesCount; ++i) ss << GetUInt32Value(i) << " "; static SqlStatementID updInstance; SqlStatement stmt = CharacterDatabase.CreateStatement(updInstance, "UPDATE item_instance SET data = ?, owner_guid = ?, text = ? WHERE guid = ?"); stmt.PExecute(ss.str().c_str(), GetOwnerGuid().GetCounter(), m_text.c_str(), guid); if (HasFlag(ITEM_FIELD_FLAGS, ITEM_DYNFLAG_WRAPPED)) { static SqlStatementID updGifts; stmt = CharacterDatabase.CreateStatement(updGifts, "UPDATE character_gifts SET guid = ? WHERE item_guid = ?"); stmt.PExecute(GetOwnerGuid().GetCounter(), GetGUIDLow()); } break; } case ITEM_REMOVED: { DeleteFromDB(guid); if (HasFlag(ITEM_FIELD_FLAGS, ITEM_DYNFLAG_WRAPPED)) DeleteGiftsFromDB(); if (HasSavedLoot()) DeleteLootFromDB(); if (HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAG_REFUNDABLE)) DeleteRefundDataFromDB(); if (HasFlag(ITEM_FIELD_FLAGS, ITEM_DYNFLAG_BOP_TRADEABLE)) DeleteSoulboundTradeableFromDB(); delete this; return; } case ITEM_UNCHANGED: return; } if (m_lootState == ITEM_LOOT_CHANGED || m_lootState == ITEM_LOOT_REMOVED) DeleteLootFromDB(); if (m_lootState == ITEM_LOOT_NEW || m_lootState == ITEM_LOOT_CHANGED) { if (Player* owner = GetOwner()) { // save money as 0 itemid data if (loot.gold) { static SqlStatementID saveGold; SqlStatement stmt = CharacterDatabase.CreateStatement(saveGold, "INSERT INTO item_loot (guid, owner_guid, itemid, amount, suffix, property) VALUES (?, ?, 0, ?, 0, 0)"); stmt.PExecute(GetGUIDLow(), owner->GetGUIDLow(), loot.gold); } static SqlStatementID saveLoot; SqlStatement stmt = CharacterDatabase.CreateStatement(saveLoot, "INSERT INTO item_loot (guid, owner_guid, itemid, amount, suffix, property) VALUES (?, ?, ?, ?, ?, ?)"); // save items and quest items (at load its all will added as normal, but this not important for item loot case) for (size_t i = 0; i < loot.GetMaxSlotInLootFor(owner); ++i) { QuestItem* qitem = NULL; LootItem* item = loot.LootItemInSlot(i, owner, &qitem); if (!item) continue; // questitems use the blocked field for other purposes if (!qitem && item->is_blocked) continue; stmt.addUInt32(GetGUIDLow()); stmt.addUInt32(owner->GetGUIDLow()); stmt.addUInt32(item->itemid); stmt.addUInt8(item->count); stmt.addUInt32(item->randomSuffix); stmt.addInt32(item->randomPropertyId); stmt.Execute(); } } } if (m_lootState != ITEM_LOOT_NONE && m_lootState != ITEM_LOOT_TEMPORARY) SetLootState(ITEM_LOOT_UNCHANGED); SetState(ITEM_UNCHANGED); }
void GameObject::Use(Unit* user) { // by default spell caster is user Unit* spellCaster = user; uint32 spellId = 0; switch(GetGoType()) { case GAMEOBJECT_TYPE_DOOR: //0 case GAMEOBJECT_TYPE_BUTTON: //1 //doors/buttons never really despawn, only reset to default state/flags UseDoorOrButton(); // activate script sWorld.ScriptsStart(sGameObjectScripts, GetDBTableGUIDLow(), spellCaster, this); return; case GAMEOBJECT_TYPE_QUESTGIVER: //2 { if(user->GetTypeId()!=TYPEID_PLAYER) return; Player* player = (Player*)user; player->PrepareQuestMenu( GetGUID() ); player->SendPreparedQuest( GetGUID() ); return; } //Sitting: Wooden bench, chairs enzz case GAMEOBJECT_TYPE_CHAIR: //7 { GameObjectInfo const* info = GetGOInfo(); if(!info) return; if(user->GetTypeId()!=TYPEID_PLAYER) return; Player* player = (Player*)user; // a chair may have n slots. we have to calculate their positions and teleport the player to the nearest one // check if the db is sane if(info->chair.slots > 0) { float lowestDist = DEFAULT_VISIBILITY_DISTANCE; float x_lowest = GetPositionX(); float y_lowest = GetPositionY(); // the object orientation + 1/2 pi // every slot will be on that straight line float orthogonalOrientation = GetOrientation()+M_PI*0.5f; // find nearest slot for(uint32 i=0; i<info->chair.slots; i++) { // the distance between this slot and the center of the go - imagine a 1D space float relativeDistance = (info->size*i)-(info->size*(info->chair.slots-1)/2.0f); float x_i = GetPositionX() + relativeDistance * cos(orthogonalOrientation); float y_i = GetPositionY() + relativeDistance * sin(orthogonalOrientation); // calculate the distance between the player and this slot float thisDistance = player->GetDistance2d(x_i, y_i); /* debug code. It will spawn a npc on each slot to visualize them. Creature* helper = player->SummonCreature(14496, x_i, y_i, GetPositionZ(), GetOrientation(), TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 10000); std::ostringstream output; output << i << ": thisDist: " << thisDistance; helper->MonsterSay(output.str().c_str(), LANG_UNIVERSAL, 0); */ if(thisDistance <= lowestDist) { lowestDist = thisDistance; x_lowest = x_i; y_lowest = y_i; } } player->TeleportTo(GetMapId(), x_lowest, y_lowest, GetPositionZ(), GetOrientation(),TELE_TO_NOT_LEAVE_TRANSPORT | TELE_TO_NOT_LEAVE_COMBAT | TELE_TO_NOT_UNSUMMON_PET); } else { // fallback, will always work player->TeleportTo(GetMapId(), GetPositionX(), GetPositionY(), GetPositionZ(), GetOrientation(),TELE_TO_NOT_LEAVE_TRANSPORT | TELE_TO_NOT_LEAVE_COMBAT | TELE_TO_NOT_UNSUMMON_PET); } player->SetStandState(PLAYER_STATE_SIT_LOW_CHAIR+info->chair.height); return; } //big gun, its a spell/aura case GAMEOBJECT_TYPE_GOOBER: //10 { GameObjectInfo const* info = GetGOInfo(); if(user->GetTypeId()==TYPEID_PLAYER) { Player* player = (Player*)user; // show page if(info->goober.pageId) { WorldPacket data(SMSG_GAMEOBJECT_PAGETEXT, 8); data << GetGUID(); player->GetSession()->SendPacket(&data); } // possible quest objective for active quests player->CastedCreatureOrGO(info->id, GetGUID(), 0); } // cast this spell later if provided spellId = info->goober.spellId; break; } case GAMEOBJECT_TYPE_CAMERA: //13 { GameObjectInfo const* info = GetGOInfo(); if(!info) return; if(user->GetTypeId()!=TYPEID_PLAYER) return; Player* player = (Player*)user; if(info->camera.cinematicId) { WorldPacket data(SMSG_TRIGGER_CINEMATIC, 4); data << info->camera.cinematicId; player->GetSession()->SendPacket(&data); } return; } //fishing bobber case GAMEOBJECT_TYPE_FISHINGNODE: //17 { if(user->GetTypeId()!=TYPEID_PLAYER) return; Player* player = (Player*)user; if(player->GetGUID() != GetOwnerGUID()) return; switch(getLootState()) { case GO_READY: // ready for loot { // 1) skill must be >= base_zone_skill // 2) if skill == base_zone_skill => 5% chance // 3) chance is linear dependence from (base_zone_skill-skill) uint32 subzone = GetAreaId(); int32 zone_skill = objmgr.GetFishingBaseSkillLevel( subzone ); if(!zone_skill) zone_skill = objmgr.GetFishingBaseSkillLevel( GetZoneId() ); //provide error, no fishable zone or area should be 0 if(!zone_skill) sLog.outErrorDb("Fishable areaId %u are not properly defined in `skill_fishing_base_level`.",subzone); int32 skill = player->GetSkillValue(SKILL_FISHING); int32 chance = skill - zone_skill + 5; int32 roll = irand(1,100); DEBUG_LOG("Fishing check (skill: %i zone min skill: %i chance %i roll: %i",skill,zone_skill,chance,roll); if(skill >= zone_skill && chance >= roll) { // prevent removing GO at spell cancel player->RemoveGameObject(this,false); SetOwnerGUID(player->GetGUID()); //fish catched player->UpdateFishingSkill(); GameObject* ok = LookupFishingHoleAround(DEFAULT_VISIBILITY_DISTANCE); if (ok) { player->SendLoot(ok->GetGUID(),LOOT_FISHINGHOLE); SetLootState(GO_JUST_DEACTIVATED); } else player->SendLoot(GetGUID(),LOOT_FISHING); } else { // fish escaped, can be deleted now SetLootState(GO_JUST_DEACTIVATED); WorldPacket data(SMSG_FISH_ESCAPED, 0); player->GetSession()->SendPacket(&data); } break; } case GO_JUST_DEACTIVATED: // nothing to do, will be deleted at next update break; default: { SetLootState(GO_JUST_DEACTIVATED); WorldPacket data(SMSG_FISH_NOT_HOOKED, 0); player->GetSession()->SendPacket(&data); break; } } if(player->m_currentSpells[CURRENT_CHANNELED_SPELL]) { player->m_currentSpells[CURRENT_CHANNELED_SPELL]->SendChannelUpdate(0); player->m_currentSpells[CURRENT_CHANNELED_SPELL]->finish(); } return; } case GAMEOBJECT_TYPE_SUMMONING_RITUAL: //18 { if(user->GetTypeId()!=TYPEID_PLAYER) return; Player* player = (Player*)user; Unit* caster = GetOwner(); GameObjectInfo const* info = GetGOInfo(); if( !caster || caster->GetTypeId()!=TYPEID_PLAYER ) return; // accept only use by player from same group for caster except caster itself if(((Player*)caster)==player || !((Player*)caster)->IsInSameRaidWith(player)) return; AddUniqueUse(player); // full amount unique participants including original summoner if(GetUniqueUseCount() < info->summoningRitual.reqParticipants) return; // in case summoning ritual caster is GO creator spellCaster = caster; if(!caster->m_currentSpells[CURRENT_CHANNELED_SPELL]) return; spellId = info->summoningRitual.spellId; // finish spell caster->m_currentSpells[CURRENT_CHANNELED_SPELL]->SendChannelUpdate(0); caster->m_currentSpells[CURRENT_CHANNELED_SPELL]->finish(); // can be deleted now SetLootState(GO_JUST_DEACTIVATED); // go to end function to spell casting break; } case GAMEOBJECT_TYPE_SPELLCASTER: //22 { SetUInt32Value(GAMEOBJECT_FLAGS,2); GameObjectInfo const* info = GetGOInfo(); if(!info) return; if(info->spellcaster.partyOnly) { Unit* caster = GetOwner(); if( !caster || caster->GetTypeId()!=TYPEID_PLAYER ) return; if(user->GetTypeId()!=TYPEID_PLAYER || !((Player*)user)->IsInSameRaidWith((Player*)caster)) return; } spellId = info->spellcaster.spellId; AddUse(); break; } case GAMEOBJECT_TYPE_MEETINGSTONE: //23 { GameObjectInfo const* info = GetGOInfo(); if(user->GetTypeId()!=TYPEID_PLAYER) return; Player* player = (Player*)user; Player* targetPlayer = ObjectAccessor::FindPlayer(player->GetSelection()); // accept only use by player from same group for caster except caster itself if(!targetPlayer || targetPlayer == player || !targetPlayer->IsInSameGroupWith(player)) return; //required lvl checks! uint8 level = player->getLevel(); if (level < info->meetingstone.minLevel || level > info->meetingstone.maxLevel) return; level = targetPlayer->getLevel(); if (level < info->meetingstone.minLevel || level > info->meetingstone.maxLevel) return; spellId = 23598; break; } case GAMEOBJECT_TYPE_FLAGSTAND: // 24 { if(user->GetTypeId()!=TYPEID_PLAYER) return; Player* player = (Player*)user; if( player->isAllowUseBattleGroundObject() ) { // in battleground check BattleGround *bg = player->GetBattleGround(); if(!bg) return; // BG flag click // AB: // 15001 // 15002 // 15003 // 15004 // 15005 bg->EventPlayerClickedOnFlag(player, this); return; //we don;t need to delete flag ... it is despawned! } break; } case GAMEOBJECT_TYPE_FLAGDROP: // 26 { if(user->GetTypeId()!=TYPEID_PLAYER) return; Player* player = (Player*)user; if( player->isAllowUseBattleGroundObject() ) { // in battleground check BattleGround *bg = player->GetBattleGround(); if(!bg) return; // BG flag dropped // WS: // 179785 - Silverwing Flag // 179786 - Warsong Flag // EotS: // 184142 - Netherstorm Flag GameObjectInfo const* info = GetGOInfo(); if(info) { switch(info->id) { case 179785: // Silverwing Flag // check if it's correct bg if(bg->GetTypeID() == BATTLEGROUND_WS) bg->EventPlayerClickedOnFlag(player, this); break; case 179786: // Warsong Flag if(bg->GetTypeID() == BATTLEGROUND_WS) bg->EventPlayerClickedOnFlag(player, this); break; case 184142: // Netherstorm Flag if(bg->GetTypeID() == BATTLEGROUND_EY) bg->EventPlayerClickedOnFlag(player, this); break; } } //this cause to call return, all flags must be deleted here!! spellId = 0; Delete(); } break; } case GAMEOBJECT_TYPE_BARBER_CHAIR: //32 { GameObjectInfo const* info = GetGOInfo(); if(!info) return; if(user->GetTypeId()!=TYPEID_PLAYER) return; Player* player = (Player*)user; // fallback, will always work player->TeleportTo(GetMapId(), GetPositionX(), GetPositionY(), GetPositionZ(), GetOrientation(),TELE_TO_NOT_LEAVE_TRANSPORT | TELE_TO_NOT_LEAVE_COMBAT | TELE_TO_NOT_UNSUMMON_PET); WorldPacket data(SMSG_ENABLE_BARBER_SHOP, 0); player->GetSession()->SendPacket(&data); player->SetStandState(PLAYER_STATE_SIT_LOW_CHAIR+info->barberChair.chairheight); return; } default: sLog.outDebug("Unknown Object Type %u", GetGoType()); break; } if(!spellId) return; SpellEntry const *spellInfo = sSpellStore.LookupEntry( spellId ); if(!spellInfo) { sLog.outError("WORLD: unknown spell id %u at use action for gameobject (Entry: %u GoType: %u )", spellId,GetEntry(),GetGoType()); return; } Spell *spell = new Spell(spellCaster, spellInfo, false); // spell target is user of GO SpellCastTargets targets; targets.setUnitTarget( user ); spell->prepare(&targets); }
void GameObject::Update(uint32 /*p_time*/) { if (IS_MO_TRANSPORT(GetGUID())) { //((Transport*)this)->Update(p_time); return; } switch (m_lootState) { case GO_NOT_READY: { switch(GetGoType()) { case GAMEOBJECT_TYPE_TRAP: { // Arming Time for GAMEOBJECT_TYPE_TRAP (6) Unit* owner = GetOwner(); if (owner && ((Player*)owner)->isInCombat()) m_cooldownTime = time(NULL) + GetGOInfo()->trap.startDelay; m_lootState = GO_READY; break; } case GAMEOBJECT_TYPE_FISHINGNODE: { // fishing code (bobber ready) if( time(NULL) > m_respawnTime - FISHING_BOBBER_READY_TIME ) { // splash bobber (bobber ready now) Unit* caster = GetOwner(); if(caster && caster->GetTypeId()==TYPEID_PLAYER) { SetGoState(0); SetUInt32Value(GAMEOBJECT_FLAGS, GO_FLAG_NODESPAWN); UpdateData udata; WorldPacket packet; BuildValuesUpdateBlockForPlayer(&udata,((Player*)caster)); udata.BuildPacket(&packet); ((Player*)caster)->GetSession()->SendPacket(&packet); WorldPacket data(SMSG_GAMEOBJECT_CUSTOM_ANIM,8+4); data << GetGUID(); data << (uint32)(0); ((Player*)caster)->SendMessageToSet(&data,true); } m_lootState = GO_READY; // can be successfully open with some chance } return; } default: m_lootState = GO_READY; // for other GOis same switched without delay to GO_READY break; } // NO BREAK for switch (m_lootState) } case GO_READY: { if (m_respawnTime > 0) // timer on { if (m_respawnTime <= time(NULL)) // timer expired { m_respawnTime = 0; m_SkillupList.clear(); m_usetimes = 0; switch (GetGoType()) { case GAMEOBJECT_TYPE_FISHINGNODE: // can't fish now { Unit* caster = GetOwner(); if(caster && caster->GetTypeId()==TYPEID_PLAYER) { if(caster->m_currentSpells[CURRENT_CHANNELED_SPELL]) { caster->m_currentSpells[CURRENT_CHANNELED_SPELL]->SendChannelUpdate(0); caster->m_currentSpells[CURRENT_CHANNELED_SPELL]->finish(false); } WorldPacket data(SMSG_FISH_NOT_HOOKED,0); ((Player*)caster)->GetSession()->SendPacket(&data); } // can be delete m_lootState = GO_JUST_DEACTIVATED; return; } case GAMEOBJECT_TYPE_DOOR: case GAMEOBJECT_TYPE_BUTTON: //we need to open doors if they are closed (add there another condition if this code breaks some usage, but it need to be here for battlegrounds) if( !GetGoState() ) SwitchDoorOrButton(false); //flags in AB are type_button and we need to add them here so no break! default: if(!m_spawnedByDefault) // despawn timer { // can be despawned or destroyed SetLootState(GO_JUST_DEACTIVATED); return; } // respawn timer GetMap()->Add(this); break; } } } // traps can have time and can not have GameObjectInfo const* goInfo = GetGOInfo(); if(goInfo->type == GAMEOBJECT_TYPE_TRAP) { // traps Unit* owner = GetOwner(); Unit* ok = NULL; // pointer to appropriate target if found any if(m_cooldownTime >= time(NULL)) return; bool IsBattleGroundTrap = false; //FIXME: this is activation radius (in different casting radius that must be selected from spell data) //TODO: move activated state code (cast itself) to GO_ACTIVATED, in this place only check activating and set state float radius = goInfo->trap.radius; if(!radius) { if(goInfo->trap.cooldown != 3) // cast in other case (at some triggering/linked go/etc explicit call) return; else { if(m_respawnTime > 0) break; radius = goInfo->trap.cooldown; // battlegrounds gameobjects has data2 == 0 && data5 == 3 IsBattleGroundTrap = true; } } bool NeedDespawn = (goInfo->trap.charges != 0); CellPair p(MaNGOS::ComputeCellPair(GetPositionX(),GetPositionY())); Cell cell(p); cell.data.Part.reserved = ALL_DISTRICT; // Note: this hack with search required until GO casting not implemented // search unfriendly creature if(owner && NeedDespawn) // hunter trap { MaNGOS::AnyUnfriendlyUnitInObjectRangeCheck u_check(this, owner, radius); MaNGOS::UnitSearcher<MaNGOS::AnyUnfriendlyUnitInObjectRangeCheck> checker(ok, u_check); CellLock<GridReadGuard> cell_lock(cell, p); TypeContainerVisitor<MaNGOS::UnitSearcher<MaNGOS::AnyUnfriendlyUnitInObjectRangeCheck>, GridTypeMapContainer > grid_object_checker(checker); cell_lock->Visit(cell_lock, grid_object_checker, *GetMap()); // or unfriendly player/pet if(!ok) { TypeContainerVisitor<MaNGOS::UnitSearcher<MaNGOS::AnyUnfriendlyUnitInObjectRangeCheck>, WorldTypeMapContainer > world_object_checker(checker); cell_lock->Visit(cell_lock, world_object_checker, *GetMap()); } } else // environmental trap { // environmental damage spells already have around enemies targeting but this not help in case not existed GO casting support // affect only players Player* p_ok = NULL; MaNGOS::AnyPlayerInObjectRangeCheck p_check(this, radius); MaNGOS::PlayerSearcher<MaNGOS::AnyPlayerInObjectRangeCheck> checker(p_ok, p_check); CellLock<GridReadGuard> cell_lock(cell, p); TypeContainerVisitor<MaNGOS::PlayerSearcher<MaNGOS::AnyPlayerInObjectRangeCheck>, WorldTypeMapContainer > world_object_checker(checker); cell_lock->Visit(cell_lock, world_object_checker, *GetMap()); ok = p_ok; } if (ok) { Unit *caster = owner ? owner : ok; caster->CastSpell(ok, goInfo->trap.spellId, true); m_cooldownTime = time(NULL) + 4; // 4 seconds if(NeedDespawn) SetLootState(GO_JUST_DEACTIVATED); // can be despawned or destroyed if(IsBattleGroundTrap && ok->GetTypeId() == TYPEID_PLAYER) { //BattleGround gameobjects case if(((Player*)ok)->InBattleGround()) if(BattleGround *bg = ((Player*)ok)->GetBattleGround()) bg->HandleTriggerBuff(GetGUID()); } } } if (m_charges && m_usetimes >= m_charges) SetLootState(GO_JUST_DEACTIVATED); // can be despawned or destroyed break; } case GO_ACTIVATED: { switch(GetGoType()) { case GAMEOBJECT_TYPE_DOOR: case GAMEOBJECT_TYPE_BUTTON: if(GetAutoCloseTime() && (m_cooldownTime < time(NULL))) { SwitchDoorOrButton(false); SetLootState(GO_JUST_DEACTIVATED); } break; } break; } case GO_JUST_DEACTIVATED: { //if Gameobject should cast spell, then this, but some GOs (type = 10) should be destroyed if (GetGoType() == GAMEOBJECT_TYPE_GOOBER) { uint32 spellId = GetGOInfo()->goober.spellId; if(spellId) { std::set<uint32>::iterator it = m_unique_users.begin(); std::set<uint32>::iterator end = m_unique_users.end(); for (; it != end; it++) { Unit* owner = Unit::GetUnit(*this, uint64(*it)); if (owner) owner->CastSpell(owner, spellId, false); } m_unique_users.clear(); m_usetimes = 0; } //any return here in case battleground traps } if(GetOwnerGUID()) { m_respawnTime = 0; Delete(); return; } //burning flags in some battlegrounds, if you find better condition, just add it if (GetGoAnimProgress() > 0) { SendObjectDeSpawnAnim(GetGUID()); //reset flags SetUInt32Value(GAMEOBJECT_FLAGS, GetGOInfo()->flags); } loot.clear(); SetLootState(GO_READY); if(!m_respawnDelayTime) return; if(!m_spawnedByDefault) { m_respawnTime = 0; return; } m_respawnTime = time(NULL) + m_respawnDelayTime; // if option not set then object will be saved at grid unload if(sWorld.getConfig(CONFIG_SAVE_RESPAWN_TIME_IMMEDIATLY)) SaveRespawnTime(); ObjectAccessor::UpdateObjectVisibility(this); break; } } }
void Item::SaveToDB() { uint32 guid = GetGUIDLow(); switch (uState) { case ITEM_NEW: { static SqlStatementID delItem ; static SqlStatementID insItem ; SqlStatement stmt = CharacterDatabase.CreateStatement(delItem, "DELETE FROM item_instance WHERE guid = ?"); stmt.PExecute(guid); std::ostringstream ss; for (uint16 i = 0; i < m_valuesCount; ++i) ss << GetUInt32Value(i) << " "; stmt = CharacterDatabase.CreateStatement(insItem, "INSERT INTO item_instance (guid,owner_guid,data) VALUES (?, ?, ?)"); stmt.PExecute(guid, GetOwnerGuid().GetCounter(), ss.str().c_str()); } break; case ITEM_CHANGED: { static SqlStatementID updInstance ; static SqlStatementID updGifts ; SqlStatement stmt = CharacterDatabase.CreateStatement(updInstance, "UPDATE item_instance SET data = ?, owner_guid = ? WHERE guid = ?"); std::ostringstream ss; for (uint16 i = 0; i < m_valuesCount; ++i) ss << GetUInt32Value(i) << " "; stmt.PExecute(ss.str().c_str(), GetOwnerGuid().GetCounter(), guid); if (HasFlag(ITEM_FIELD_FLAGS, ITEM_DYNFLAG_WRAPPED)) { stmt = CharacterDatabase.CreateStatement(updGifts, "UPDATE character_gifts SET guid = ? WHERE item_guid = ?"); stmt.PExecute(GetOwnerGuid().GetCounter(), GetGUIDLow()); } } break; case ITEM_REMOVED: { static SqlStatementID delItemText; static SqlStatementID delInst ; static SqlStatementID delGifts ; static SqlStatementID delLoot ; if (uint32 item_text_id = GetUInt32Value(ITEM_FIELD_ITEM_TEXT_ID)) { SqlStatement stmt = CharacterDatabase.CreateStatement(delItemText, "DELETE FROM item_text WHERE id = ?"); stmt.PExecute(item_text_id); } SqlStatement stmt = CharacterDatabase.CreateStatement(delInst, "DELETE FROM item_instance WHERE guid = ?"); stmt.PExecute(guid); if (HasFlag(ITEM_FIELD_FLAGS, ITEM_DYNFLAG_WRAPPED)) { stmt = CharacterDatabase.CreateStatement(delGifts, "DELETE FROM character_gifts WHERE item_guid = ?"); stmt.PExecute(GetGUIDLow()); } if (HasSavedLoot()) { stmt = CharacterDatabase.CreateStatement(delLoot, "DELETE FROM item_loot WHERE guid = ?"); stmt.PExecute(GetGUIDLow()); } delete this; return; } case ITEM_UNCHANGED: return; } if (m_lootState == ITEM_LOOT_CHANGED || m_lootState == ITEM_LOOT_REMOVED) { static SqlStatementID delLoot ; SqlStatement stmt = CharacterDatabase.CreateStatement(delLoot, "DELETE FROM item_loot WHERE guid = ?"); stmt.PExecute(GetGUIDLow()); } if (loot && (m_lootState == ITEM_LOOT_NEW || m_lootState == ITEM_LOOT_CHANGED)) { if (Player* owner = GetOwner()) { static SqlStatementID saveGold ; static SqlStatementID saveLoot ; // save money as 0 itemid data if (loot->GetGoldAmount()) { SqlStatement stmt = CharacterDatabase.CreateStatement(saveGold, "INSERT INTO item_loot (guid,owner_guid,itemid,amount,property) VALUES (?, ?, 0, ?, 0)"); stmt.PExecute(GetGUIDLow(), owner->GetGUIDLow(), loot->GetGoldAmount()); } SqlStatement stmt = CharacterDatabase.CreateStatement(saveLoot, "INSERT INTO item_loot (guid,owner_guid,itemid,amount,property) VALUES (?, ?, ?, ?, ?)"); // save items and quest items (at load its all will added as normal, but this not important for item loot case) LootItemList lootList; loot->GetLootItemsListFor(owner, lootList); for (LootItemList::const_iterator lootItr = lootList.begin(); lootItr != lootList.end(); ++lootItr) { LootItem* lootItem = *lootItr; stmt.addUInt32(GetGUIDLow()); stmt.addUInt32(owner->GetGUIDLow()); stmt.addUInt32(lootItem->itemId); stmt.addUInt8(lootItem->count); stmt.addInt32(lootItem->randomPropertyId); stmt.Execute(); } } } if (m_lootState != ITEM_LOOT_NONE && m_lootState != ITEM_LOOT_TEMPORARY) SetLootState(ITEM_LOOT_UNCHANGED); SetState(ITEM_UNCHANGED); }
void Item::SaveToDB() { uint32 guid = GetGUIDLow(); switch (uState) { case ITEM_NEW: { std::string text = m_text; CharacterDatabase.escape_string(text); CharacterDatabase.PExecute( "DELETE FROM item_instance WHERE guid = '%u'", guid ); std::ostringstream ss; ss << "INSERT INTO item_instance (guid,owner_guid,data,text) VALUES (" << guid << "," << GetOwnerGuid().GetCounter() << ",'"; for(uint16 i = 0; i < m_valuesCount; ++i ) ss << GetUInt32Value(i) << " "; ss << "', '" << text << "')"; CharacterDatabase.Execute( ss.str().c_str() ); } break; case ITEM_CHANGED: { std::string text = m_text; CharacterDatabase.escape_string(text); std::ostringstream ss; ss << "UPDATE item_instance SET data = '"; for(uint16 i = 0; i < m_valuesCount; ++i ) ss << GetUInt32Value(i) << " "; ss << "', owner_guid = '" << GetOwnerGuid().GetCounter(); ss << "', text = '" << text << "' WHERE guid = '" << guid << "'"; CharacterDatabase.Execute( ss.str().c_str() ); if (HasFlag(ITEM_FIELD_FLAGS, ITEM_DYNFLAG_WRAPPED)) CharacterDatabase.PExecute("UPDATE character_gifts SET guid = '%u' WHERE item_guid = '%u'", GetOwnerGuid().GetCounter(), GetGUIDLow()); } break; case ITEM_REMOVED: { CharacterDatabase.PExecute("DELETE FROM item_instance WHERE guid = '%u'", guid); if (HasFlag(ITEM_FIELD_FLAGS, ITEM_DYNFLAG_WRAPPED)) CharacterDatabase.PExecute("DELETE FROM character_gifts WHERE item_guid = '%u'", GetGUIDLow()); if (HasSavedLoot()) CharacterDatabase.PExecute("DELETE FROM item_loot WHERE guid = '%u'", GetGUIDLow()); delete this; return; } case ITEM_UNCHANGED: return; } if (m_lootState == ITEM_LOOT_CHANGED || m_lootState == ITEM_LOOT_REMOVED) CharacterDatabase.PExecute("DELETE FROM item_loot WHERE guid = '%u'", GetGUIDLow()); if (m_lootState == ITEM_LOOT_NEW || m_lootState == ITEM_LOOT_CHANGED) { if(Player* owner = GetOwner()) { // save money as 0 itemid data if (loot.gold) CharacterDatabase.PExecute("INSERT INTO item_loot (guid,owner_guid,itemid,amount,suffix,property) " "VALUES (%u, %u, 0, %u, 0, 0)", GetGUIDLow(), owner->GetGUIDLow(), loot.gold); // save items and quest items (at load its all will added as normal, but this not important for item loot case) for (size_t i = 0; i < loot.GetMaxSlotInLootFor(owner); ++i) { QuestItem *qitem = NULL; LootItem *item = loot.LootItemInSlot(i,owner,&qitem); if(!item) continue; // questitems use the blocked field for other purposes if (!qitem && item->is_blocked) continue; CharacterDatabase.PExecute("INSERT INTO item_loot (guid,owner_guid,itemid,amount,suffix,property) " "VALUES (%u, %u, %u, %u, %u, %i)", GetGUIDLow(), owner->GetGUIDLow(), item->itemid, item->count, item->randomSuffix, item->randomPropertyId); } } } if (m_lootState != ITEM_LOOT_NONE && m_lootState != ITEM_LOOT_TEMPORARY) SetLootState(ITEM_LOOT_UNCHANGED); SetState(ITEM_UNCHANGED); }
void GameObject::Update(uint32 p_time) { if (GUID_HIPART(GetGUID()) == HIGHGUID_TRANSPORT) { //((Transport*)this)->Update(p_time); return; } switch (m_lootState) { case GO_NOT_READY: if (GetGoType()==17) { // fishing code (bobber ready) if( time(NULL) > m_respawnTime - FISHING_BOBBER_READY_TIME ) { // splash bobber (bobber ready now) Unit* caster = GetOwner(); if(caster && caster->GetTypeId()==TYPEID_PLAYER) { SetUInt32Value(GAMEOBJECT_STATE, 0); SetUInt32Value(GAMEOBJECT_FLAGS, 32); UpdateData udata; WorldPacket packet; BuildValuesUpdateBlockForPlayer(&udata,((Player*)caster)); udata.BuildPacket(&packet); ((Player*)caster)->GetSession()->SendPacket(&packet); WorldPacket data; data.Initialize(SMSG_GAMEOBJECT_CUSTOM_ANIM); data << GetGUID(); data << (uint32)(0); ((Player*)caster)->SendMessageToSet(&data,true); } m_lootState = GO_CLOSED; // can be succesfully open with some chance } return; } m_lootState = GO_CLOSED; // for not bobber is same as GO_CLOSED // NO BREAK case GO_CLOSED: if (m_respawnTime > 0) // timer on { if (m_respawnTime <= time(NULL)) // timer expired { m_respawnTime = 0; m_SkillupList.clear(); switch (GetGoType()) { case GAMEOBJECT_TYPE_FISHINGNODE: // can't fish now { Unit* caster = GetOwner(); if(caster && caster->GetTypeId()==TYPEID_PLAYER) { if(caster->m_currentSpell) { caster->m_currentSpell->SendChannelUpdate(0); caster->m_currentSpell->finish(false); } WorldPacket data; data.Initialize(SMSG_FISH_NOT_HOOKED); ((Player*)caster)->GetSession()->SendPacket(&data); } m_lootState = GO_LOOTED; // can be delete return; } case GAMEOBJECT_TYPE_DOOR: SetUInt32Value (GAMEOBJECT_FLAGS, m_flags); SetUInt32Value (GAMEOBJECT_STATE, 1); break; case GAMEOBJECT_TYPE_TRAP: break; default: if(GetOwnerGUID()) // despawn timer { m_respawnTime = 0; Delete(); return; } // respawn timer MapManager::Instance().GetMap(GetMapId(), this)->Add(this); break; } } } break; case GO_OPEN: break; case GO_LOOTED: if(GetOwnerGUID()) { m_respawnTime = 0; Delete(); return; } loot.clear(); SetLootState(GO_CLOSED); SendDestroyObject(GetGUID()); m_respawnTime = time(NULL) + m_respawnDelayTime; // if option not set then object will be ssaved at grif unload if(sWorld.getConfig(CONFIG_SAVE_RESPAWN_TIME_IMMEDIATLY)) SaveRespawnTime(); break; } SpellEntry const *createSpell = m_spellId ? sSpellStore.LookupEntry(m_spellId) : NULL; if (!createSpell) return; int i; for (i = 0; i < 3; i++) if (createSpell->Effect[i] == SPELL_EFFECT_SUMMON_OBJECT_SLOT1) break; if (i<3) { // traps CellPair p(MaNGOS::ComputeCellPair(GetPositionX(),GetPositionY())); Cell cell = RedZone::GetZone(p); cell.data.Part.reserved = ALL_DISTRICT; Unit* owner = GetOwner(); if (!owner) { m_respawnTime = 0; // to prevent save respawn timer Delete(); return; } Unit* ok = NULL; // pointer to appropriate target if found any float radius = GetRadius(sSpellRadiusStore.LookupEntry(createSpell->EffectRadiusIndex[i])); MaNGOS::AnyUnfriendlyUnitInObjectRangeCheck u_check(this, owner, radius); MaNGOS::UnitSearcher<MaNGOS::AnyUnfriendlyUnitInObjectRangeCheck> checker(ok, u_check); CellLock<GridReadGuard> cell_lock(cell, p); // search unfriedly creature { TypeContainerVisitor<MaNGOS::UnitSearcher<MaNGOS::AnyUnfriendlyUnitInObjectRangeCheck>, GridTypeMapContainer > grid_object_checker(checker); cell_lock->Visit(cell_lock, grid_object_checker, *MapManager::Instance().GetMap(GetMapId(), this)); } // or unfriendly player/pet if(!ok) { TypeContainerVisitor<MaNGOS::UnitSearcher<MaNGOS::AnyUnfriendlyUnitInObjectRangeCheck>, WorldTypeMapContainer > world_object_checker(checker); cell_lock->Visit(cell_lock, world_object_checker, *MapManager::Instance().GetMap(GetMapId(), this)); } if (ok) { owner->CastSpell(ok, GetGOInfo()->sound3, true); m_respawnTime = 0; // to prevent save respawn timer Delete(); } } if (m_usetimes >= 5) { m_respawnTime = 0; // to prevent save respawn timer Delete(); } }