From 89f97b85fd87465fe24d44be3fd938b032938a1f Mon Sep 17 00:00:00 2001 From: Schmoozerd Date: Fri, 31 May 2013 11:12:32 +0100 Subject: [PATCH] [c12600] Add condition_id support to npc_spellclick_spells --- sql/mangos.sql | 20 +-- ...c12602_01_mangos_npc_spellclick_spells.sql | 3 + src/game/ObjectMgr.cpp | 69 ++++---- src/game/ObjectMgr.h | 6 +- src/game/Player.cpp | 2 +- src/game/SpellHandler.cpp | 2 +- src/game/VehicleHandler.cpp | 148 ++++++++++++++++-- src/shared/revision_nr.h | 2 +- src/shared/revision_sql.h | 2 +- 9 files changed, 194 insertions(+), 60 deletions(-) create mode 100644 sql/updates/c12602_01_mangos_npc_spellclick_spells.sql diff --git a/sql/mangos.sql b/sql/mangos.sql index 869226141..cd9f90a53 100644 --- a/sql/mangos.sql +++ b/sql/mangos.sql @@ -1425,7 +1425,7 @@ CREATE TABLE `db_version` ( `version` varchar(120) DEFAULT NULL, `creature_ai_version` varchar(120) DEFAULT NULL, `cache_id` int(10) DEFAULT '0', - `required_c12601_01_mangos_spell_area` bit(1) default NULL + `required_c12602_01_mangos_npc_spellclick_spells` bit(1) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Used DB version notes'; /*!40101 SET character_set_client = @saved_cs_client */; @@ -1435,7 +1435,7 @@ CREATE TABLE `db_version` ( LOCK TABLES `db_version` WRITE; /*!40000 ALTER TABLE `db_version` DISABLE KEYS */; -INSERT INTO `db_version` (`version`, `creature_ai_version`, `cache_id`, `required_c12601_01_mangos_spell_area`) VALUES +INSERT INTO `db_version` (`version`, `creature_ai_version`, `cache_id`, `required_c12602_01_mangos_npc_spellclick_spells`) VALUES ('Mangos default database.','Creature EventAI not provided.',0,NULL); /*!40000 ALTER TABLE `db_version` ENABLE KEYS */; UNLOCK TABLES; @@ -4209,14 +4209,14 @@ DROP TABLE IF EXISTS `npc_spellclick_spells`; /*!40101 SET @saved_cs_client = @@character_set_client */; /*!40101 SET character_set_client = utf8 */; CREATE TABLE `npc_spellclick_spells` ( - `npc_entry` int(10) unsigned NOT NULL COMMENT 'reference to creature_template', - `spell_id` int(10) unsigned NOT NULL COMMENT 'spell which should be casted ', - `quest_start` mediumint(8) unsigned NOT NULL COMMENT 'reference to quest_template', - `quest_start_active` tinyint(1) unsigned NOT NULL DEFAULT '0', - `quest_end` mediumint(8) unsigned NOT NULL DEFAULT '0', - `cast_flags` tinyint(3) unsigned NOT NULL COMMENT 'first bit defines caster: 1=player, 0=creature; second bit defines target, same mapping as caster bit' -) ENGINE=MyISAM DEFAULT CHARSET=utf8; -/*!40101 SET character_set_client = @saved_cs_client */; + `npc_entry` int unsigned NOT NULL COMMENT 'reference to creature_template', + `spell_id` int unsigned NOT NULL COMMENT 'spell which should be casted ', + `quest_start` mediumint(8) unsigned NOT NULL COMMENT 'reference to quest_template', + `quest_start_active` tinyint(1) unsigned NOT NULL default '0', + `quest_end` mediumint(8) unsigned NOT NULL default '0', + `cast_flags` tinyint unsigned NOT NULL COMMENT 'first bit defines caster: 1=player, 0=creature; second bit defines target, same mapping as caster bit', + `condition_id` mediumint(8) unsigned NOT NULL default '0' +) ENGINE = MYISAM DEFAULT CHARSET=utf8; -- -- Dumping data for table `npc_spellclick_spells` diff --git a/sql/updates/c12602_01_mangos_npc_spellclick_spells.sql b/sql/updates/c12602_01_mangos_npc_spellclick_spells.sql new file mode 100644 index 000000000..258e17ce3 --- /dev/null +++ b/sql/updates/c12602_01_mangos_npc_spellclick_spells.sql @@ -0,0 +1,3 @@ +ALTER TABLE db_version CHANGE COLUMN required_c12601_01_mangos_spell_area required_c12602_01_mangos_npc_spellclick_spells bit; + +ALTER TABLE npc_spellclick_spells ADD COLUMN `condition_id` mediumint(8) unsigned NOT NULL default '0' AFTER cast_flags; diff --git a/src/game/ObjectMgr.cpp b/src/game/ObjectMgr.cpp index ca7f54a1f..4e1394679 100755 --- a/src/game/ObjectMgr.cpp +++ b/src/game/ObjectMgr.cpp @@ -109,8 +109,11 @@ LanguageDesc const* GetLanguageDescByID(uint32 lang) return NULL; } -bool SpellClickInfo::IsFitToRequirements(Player const* player) const +bool SpellClickInfo::IsFitToRequirements(Player const* player, Creature const* clickedCreature) const { + if (conditionId) + return sObjectMgr.IsPlayerMeetToCondition(conditionId, player, player->GetMap(), clickedCreature, CONDITION_FROM_SPELLCLICK); + if (questStart) { // not in expected required quest state @@ -6965,8 +6968,8 @@ void ObjectMgr::LoadNPCSpellClickSpells() uint32 count = 0; mSpellClickInfoMap.clear(); - // 0 1 2 3 4 5 - QueryResult* result = WorldDatabase.Query("SELECT npc_entry, spell_id, quest_start, quest_start_active, quest_end, cast_flags FROM npc_spellclick_spells"); + // 0 1 2 3 4 5 6 + QueryResult* result = WorldDatabase.Query("SELECT npc_entry, spell_id, quest_start, quest_start_active, quest_end, cast_flags, condition_id FROM npc_spellclick_spells"); if (!result) { @@ -6986,7 +6989,15 @@ void ObjectMgr::LoadNPCSpellClickSpells() Field* fields = result->Fetch(); bar.step(); - uint32 npc_entry = fields[0].GetUInt32(); + SpellClickInfo info; + uint32 npc_entry = fields[0].GetUInt32(); + info.spellId = fields[1].GetUInt32(); + info.questStart = fields[2].GetUInt32(); + info.questStartCanActive = fields[3].GetBool(); + info.questEnd = fields[4].GetUInt32(); + info.castFlags = fields[5].GetUInt8(); + info.conditionId = fields[6].GetUInt16(); + CreatureInfo const* cInfo = GetCreatureTemplate(npc_entry); if (!cInfo) { @@ -6994,46 +7005,35 @@ void ObjectMgr::LoadNPCSpellClickSpells() continue; } - uint32 spellid = fields[1].GetUInt32(); - SpellEntry const* spellinfo = sSpellStore.LookupEntry(spellid); + SpellEntry const* spellinfo = sSpellStore.LookupEntry(info.spellId); if (!spellinfo) { - sLog.outErrorDb("Table npc_spellclick_spells references unknown spellid %u. Skipping entry.", spellid); + sLog.outErrorDb("Table npc_spellclick_spells references unknown spellid %u. Skipping entry.", info.spellId); continue; } - uint32 quest_start = fields[2].GetUInt32(); - - // quest might be 0 to enable spellclick independent of any quest - if (quest_start) + if (info.conditionId && !sConditionStorage.LookupEntry(info.conditionId)) { - if (mQuestTemplates.find(quest_start) == mQuestTemplates.end()) + sLog.outErrorDb("Table npc_spellclick_spells references unknown condition %u. Skipping entry.", info.conditionId); + continue; + } + else if (!info.conditionId) // TODO Drop block after finished converting + { + // quest might be 0 to enable spellclick independent of any quest + if (info.questStart && mQuestTemplates.find(info.questStart) == mQuestTemplates.end()) { - sLog.outErrorDb("Table npc_spellclick_spells references unknown start quest %u. Skipping entry.", quest_start); + sLog.outErrorDb("Table npc_spellclick_spells references unknown start quest %u. Skipping entry.", info.questStart); + continue; + } + + // quest might be 0 to enable spellclick active infinity after start quest + if (info.questEnd && mQuestTemplates.find(info.questEnd) == mQuestTemplates.end()) + { + sLog.outErrorDb("Table npc_spellclick_spells references unknown end quest %u. Skipping entry.", info.questEnd); continue; } } - bool quest_start_active = fields[3].GetBool(); - - uint32 quest_end = fields[4].GetUInt32(); - // quest might be 0 to enable spellclick active infinity after start quest - if (quest_end) - { - if (mQuestTemplates.find(quest_end) == mQuestTemplates.end()) - { - sLog.outErrorDb("Table npc_spellclick_spells references unknown end quest %u. Skipping entry.", quest_end); - continue; - } - } - - uint8 castFlags = fields[5].GetUInt8(); - SpellClickInfo info; - info.spellId = spellid; - info.questStart = quest_start; - info.questStartCanActive = quest_start_active; - info.questEnd = quest_end; - info.castFlags = castFlags; mSpellClickInfoMap.insert(SpellClickInfoMap::value_type(npc_entry, info)); // mark creature template as spell clickable @@ -7826,7 +7826,8 @@ char const* conditionSourceToStr[] = "event AI", "hardcoded", "vendor's item check", - "spell_area check" + "spell_area check", + "npc_spellclick_spells check" }; // Checks if player meets the condition diff --git a/src/game/ObjectMgr.h b/src/game/ObjectMgr.h index 8cfcc7250..ed5588215 100755 --- a/src/game/ObjectMgr.h +++ b/src/game/ObjectMgr.h @@ -66,12 +66,13 @@ struct SpellClickInfo uint32 questEnd; // quest end (quest don't must be rewarded for spell apply) bool questStartCanActive; // if true then quest start can be active (not only rewarded) uint8 castFlags; + uint16 conditionId; // intends to replace questStart, questEnd, questStartCanActive // helpers - bool IsFitToRequirements(Player const* player) const; + bool IsFitToRequirements(Player const* player, Creature const* clickedCreature) const; }; -typedef std::multimap SpellClickInfoMap; +typedef std::multimap SpellClickInfoMap; typedef std::pair SpellClickInfoMapBounds; struct AreaTrigger @@ -417,6 +418,7 @@ enum ConditionSource // From where was th CONDITION_FROM_HARDCODED = 5, // Used to check a hardcoded event - not actually a condition CONDITION_FROM_VENDOR = 6, // Used to check a condition from a vendor CONDITION_FROM_SPELL_AREA = 7, // Used to check a condition from spell_area table + CONDITION_FROM_SPELLCLICK = 8, // Used to check a condition from npc_spellclick_spells table }; class PlayerCondition diff --git a/src/game/Player.cpp b/src/game/Player.cpp index 158c7659d..3e371b647 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -22625,7 +22625,7 @@ bool Player::canSeeSpellClickOn(Creature const* c) const SpellClickInfoMapBounds clickPair = sObjectMgr.GetSpellClickInfoMapBounds(c->GetEntry()); for (SpellClickInfoMap::const_iterator itr = clickPair.first; itr != clickPair.second; ++itr) - if (itr->second.IsFitToRequirements(this)) + if (itr->second.IsFitToRequirements(this, c)) return true; return false; diff --git a/src/game/SpellHandler.cpp b/src/game/SpellHandler.cpp index a16725f90..6e33d5248 100644 --- a/src/game/SpellHandler.cpp +++ b/src/game/SpellHandler.cpp @@ -601,7 +601,7 @@ void WorldSession::HandleSpellClick(WorldPacket& recv_data) SpellClickInfoMapBounds clickPair = sObjectMgr.GetSpellClickInfoMapBounds(unit->GetEntry()); for (SpellClickInfoMap::const_iterator itr = clickPair.first; itr != clickPair.second; ++itr) { - if (itr->second.IsFitToRequirements(_player)) + if (itr->second.IsFitToRequirements(_player, unit)) { Unit* caster = (itr->second.castFlags & 0x1) ? (Unit*)_player : (Unit*)unit; Unit* target = (itr->second.castFlags & 0x2) ? (Unit*)_player : (Unit*)unit; diff --git a/src/game/VehicleHandler.cpp b/src/game/VehicleHandler.cpp index 614b86b09..46e4d1227 100644 --- a/src/game/VehicleHandler.cpp +++ b/src/game/VehicleHandler.cpp @@ -26,20 +26,148 @@ #include "Vehicle.h" #include "ObjectMgr.h" -void WorldSession::HandleDismissControlledVehicle(WorldPacket& recv_data) +void WorldSession::HandleDismissControlledVehicle(WorldPacket& recvPacket) { - DEBUG_LOG("WORLD: Recvd CMSG_DISMISS_CONTROLLED_VEHICLE"); - recv_data.hexlike(); + DEBUG_LOG("WORLD: Received opcode CMSG_DISMISS_CONTROLLED_VEHICLE"); + recvPacket.hexlike(); - ObjectGuid guid; - MovementInfo mi; + ObjectGuid vehicleGuid; + MovementInfo movementInfo; // Not used at the moment - recv_data >> guid.ReadAsPacked(); - recv_data >> mi; + recvPacket >> vehicleGuid.ReadAsPacked(); + recvPacket >> movementInfo; - ObjectGuid vehicleGUID = _player->GetCharmGuid(); - if (!vehicleGUID) // something wrong here... + TransportInfo* transportInfo = _player->GetTransportInfo(); + if (!transportInfo || !transportInfo->IsOnVehicle()) return; - _player->m_movementInfo = mi; + Unit* vehicle = (Unit*)transportInfo->GetTransport(); + + // Something went wrong + if (vehicleGuid != vehicle->GetObjectGuid()) + return; + + // Remove Vehicle Control Aura + vehicle->RemoveSpellsCausingAura(SPELL_AURA_CONTROL_VEHICLE, _player->GetObjectGuid()); +} + +void WorldSession::HandleRequestVehicleExit(WorldPacket& recvPacket) +{ + DEBUG_LOG("WORLD: Received opcode CMSG_REQUEST_VEHICLE_EXIT"); + recvPacket.hexlike(); + + TransportInfo* transportInfo = _player->GetTransportInfo(); + if (!transportInfo || !transportInfo->IsOnVehicle()) + return; + + ((Unit*)transportInfo->GetTransport())->RemoveSpellsCausingAura(SPELL_AURA_CONTROL_VEHICLE, _player->GetObjectGuid()); +} + +void WorldSession::HandleRequestVehicleSwitchSeat(WorldPacket& recvPacket) +{ + DEBUG_LOG("WORLD: Received opcode CMSG_REQUEST_VEHICLE_SWITCH_SEAT"); + recvPacket.hexlike(); + + ObjectGuid vehicleGuid; + uint8 seat; + + recvPacket >> vehicleGuid.ReadAsPacked(); + recvPacket >> seat; + + TransportInfo* transportInfo = _player->GetTransportInfo(); + if (!transportInfo || !transportInfo->IsOnVehicle()) + return; + + Unit* vehicle = (Unit*)transportInfo->GetTransport(); + + // Something went wrong + if (vehicleGuid != vehicle->GetObjectGuid()) + return; + + vehicle->GetVehicleInfo()->SwitchSeat(_player, seat); +} + +void WorldSession::HandleChangeSeatsOnControlledVehicle(WorldPacket& recvPacket) +{ + DEBUG_LOG("WORLD: Received opcode CMSG_CHANGE_SEATS_ON_CONTROLLED_VEHICLE"); + recvPacket.hexlike(); + + ObjectGuid srcVehicleGuid; + MovementInfo movementInfo; + ObjectGuid destVehicleGuid; + uint8 seat; + + recvPacket >> srcVehicleGuid.ReadAsPacked(); + recvPacket >> movementInfo; // Not used at the moment + recvPacket >> destVehicleGuid.ReadAsPacked(); + recvPacket >> seat; + + TransportInfo* transportInfo = _player->GetTransportInfo(); + if (!transportInfo || !transportInfo->IsOnVehicle()) + return; + + Unit* srcVehicle = (Unit*)transportInfo->GetTransport(); + + // Something went wrong + if (srcVehicleGuid != srcVehicle->GetObjectGuid()) + return; + + if (srcVehicleGuid != destVehicleGuid) + { + Unit* destVehicle = _player->GetMap()->GetUnit(destVehicleGuid); + + if (!destVehicle || !destVehicle->IsVehicle()) + return; + + // Change vehicle is not possible + if (destVehicle->GetVehicleInfo()->GetVehicleEntry()->m_flags & VEHICLE_FLAG_DISABLE_SWITCH) + return; + + SpellClickInfoMapBounds clickPair = sObjectMgr.GetSpellClickInfoMapBounds(destVehicle->GetEntry()); + for (SpellClickInfoMap::const_iterator itr = clickPair.first; itr != clickPair.second; ++itr) + if (itr->second.IsFitToRequirements(_player, destVehicle->GetTypeId() == TYPEID_UNIT ? (Creature*)destVehicle : NULL)) + _player->CastSpell(destVehicle, itr->second.spellId, true); + } + else + srcVehicle->GetVehicleInfo()->SwitchSeat(_player, seat); +} + +void WorldSession::HandleRideVehicleInteract(WorldPacket& recvPacket) +{ + DEBUG_LOG("WORLD: Received opcode CMSG_RIDE_VEHICLE_INTERACT"); + recvPacket.hexlike(); + + ObjectGuid playerGuid; + recvPacket >> playerGuid; + + Player* vehicle = _player->GetMap()->GetPlayer(playerGuid); + + if (!vehicle || !vehicle->IsVehicle()) + return; + + // Only allowed if in same raid + if (!vehicle->IsInSameRaidWith(_player)) + return; + + _player->CastSpell(vehicle, SPELL_RIDE_VEHICLE_HARDCODED, true); +} + +void WorldSession::HandleEjectPassenger(WorldPacket& recvPacket) +{ + DEBUG_LOG("WORLD: Received opcode CMSG_CONTROLLER_EJECT_PASSENGER"); + recvPacket.hexlike(); + + ObjectGuid passengerGuid; + recvPacket >> passengerGuid; + + Unit* passenger = _player->GetMap()->GetUnit(passengerGuid); + + if (!passenger || !passenger->IsBoarded()) + return; + + // _player must be transporting passenger + if (!_player->IsVehicle() || !_player->GetVehicleInfo()->HasOnBoard(passenger)) + return; + + _player->RemoveSpellsCausingAura(SPELL_AURA_CONTROL_VEHICLE, passengerGuid); } diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 8fd7de3b9..533d5fabf 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "12599" + #define REVISION_NR "12600" #endif // __REVISION_NR_H__ diff --git a/src/shared/revision_sql.h b/src/shared/revision_sql.h index 710d14019..6612e4e25 100644 --- a/src/shared/revision_sql.h +++ b/src/shared/revision_sql.h @@ -1,6 +1,6 @@ #ifndef __REVISION_SQL_H__ #define __REVISION_SQL_H__ #define REVISION_DB_CHARACTERS "required_12447_02_characters_calendar_invites" - #define REVISION_DB_MANGOS "required_c12601_01_mangos_spell_area" + #define REVISION_DB_MANGOS "required_12602_01_mangos_npc_spellclick_spells" #define REVISION_DB_REALMD "required_c12484_02_realmd_account_access" #endif // __REVISION_SQL_H__