Core/Vehicles: Correct usage of npc_spellclick_spells instead of blatant hacks for vehicle entry.

Note: This may break a few vehicles, but only due to the absence of proper, non-hackish data.
This commit is contained in:
Machiavelli
2011-02-26 23:00:09 +01:00
parent 8497fb27e9
commit 3ac80ee3a4
9 changed files with 179 additions and 58 deletions
@@ -0,0 +1,68 @@
UPDATE `creature_template` SET `npcflag`=`npcflag`|16777216 WHERE `entry` IN (SELECT `npc_entry` FROM `npc_spellclick_spells`);
DELETE FROM `npc_spellclick_spells` WHERE `npc_entry` IN (32640,32633,31861,31862,25743,27661,27258,27755,27756,27692,40725,32286,29929,29602,29709,27626,28851,
34120,30403,26813,26523,27496,27714,27996,28605,28606,28607,28833,30066,32930,28312,32627,33060,33067,33062,33109,34994,30234,27629,27924,28061,28192,28669,
28670,28817,28864,2914,29460,29679,29918,30468,30470,35064,30585,30645,33217,33319,33321,33519,33844,33845,39714);
INSERT INTO `npc_spellclick_spells` (`npc_entry`,`spell_id`,`quest_start`,`quest_start_active`,`quest_end`,`cast_flags`,`aura_required`,`aura_forbidden`,`user_type`) VALUES
(32640,61424,0,0,0,1,0,0,0), -- Traveler's Tundra Mammoth
(32633,61424,0,0,0,1,0,0,0), -- Traveler's Tundra Mammoth
(31861,61466,0,0,0,1,0,0,0), -- Grand Black War Mammoth
(31862,61466,0,0,0,1,0,0,0), -- Grand Black War Mammoth
(25743,46260,0,0,0,1,0,0,0), -- Wooly Mammoth Bull
(27661,48365,0,0,0,1,0,0,0), -- Wintergarde Gryphon
(27258,48365,0,0,0,1,0,0,0), -- Wintergarde Gryphoworldn
(27755,49460,0,0,0,1,0,0,0), -- Amber Drake
(27756,49464,0,0,0,1,0,0,0), -- Ruby Drake
(27692,49346,0,0,0,1,0,0,0), -- Emerald Drake
(40725,75953,0,0,0,1,0,0,0), -- X-53 Touring Rocket
(32286,61666,0,0,0,1,0,0,0), -- Mekgineer's Chopper
(29929,58961,0,0,0,1,0,0,0), -- Mechano-hog
(29602,54908,0,0,0,1,0,0,0), -- Icefang
(29709,55029,0,0,0,1,0,0,0), -- Freed Proto-Drake
(27626,49138,0,0,0,1,0,0,0), -- Tatjana's Horse
(28851,52600,0,0,0,1,0,0,0), -- Enraged Mammoth
(34120,55089,0,0,0,1,0,0,0), -- Brann's Flying Machine
(30403,56699,0,0,0,1,0,0,0), -- Nergeld
(26813,47424,0,0,0,1,0,0,0), -- Kor'kron War Rider
(26523,48296,0,0,0,1,0,0,0), -- Forsaken Blight Spreader
(27496,48881,0,0,0,1,0,0,0), -- Refurbished Shredder
(27714,49584,0,0,0,1,0,0,0), -- 7th Legion Chain Gun
(27996,50343,0,0,0,1,0,0,0), -- Wyrmrest Vanquisher
(28605,52263,0,0,0,1,0,0,0), -- Havenshire Stallion
(28606,52263,0,0,0,1,0,0,0), -- Havenshire Mare
(28607,52263,0,0,0,1,0,0,0), -- Havenshire Colt
(28833,52447,0,0,0,1,0,0,0), -- Scarlet Cannon
(30066,56678,0,0,0,1,0,0,0), -- Argent Skytalon
(28312,60968,0,0,0,1,0,0,0), -- Wintergrasp Siege Engine
(32627,60968,0,0,0,1,0,0,0), -- Wintergrasp Siege Engine
(33060,65031,0,0,0,1,0,0,0), -- Salvaged Siege Engine
(33067,65031,0,0,0,1,0,0,0), -- Salvaged Siege Turret
(33062,65030,0,0,0,1,0,0,0), -- Salvaged Chopper
(33109,62309,0,0,0,1,0,0,0), -- Salvaged Demolisher
(34944,68458,0,0,0,1,0,0,0), -- Keep Cannon
-- These use a 'proxy' cast. They summon a similar creature with SummonProperties.category = 4
(30234,56378,0,0,0,1,0,0,0), -- Hover Disk
(27629,49207,0,0,0,1,0,0,0), -- Wyrmrest Defender
(27924,50007,0,0,0,1,0,0,0), -- Dragonflayer Harpoon
(28061,50557,0,0,0,1,0,0,0), -- Wintergarde Gryphon
(28192,50860,0,0,0,1,0,0,0), -- Archmage Pentarus' Flying Machine
(28669,52190,0,0,0,1,0,0,0), -- Flying Fiend
(28670,53173,0,0,0,1,0,0,0), -- Frostblood Vanquisher
(28817,52462,0,0,0,1,0,0,0), -- Mine Car
(28864,52589,0,0,0,1,0,0,0), -- Scourge Gryphon
(29414,18277,0,0,0,1,0,0,0), -- Bone Gryphon
(29460,54513,0,0,0,1,0,0,0), -- Frigit Proto-Drake
(29679,54952,0,0,0,1,0,0,0), -- Hyldsmeet Proto-Drake
(29918,54301,0,0,0,1,0,0,0), -- Warbear Matriarch
(30468,56795,0,0,0,1,0,0,0), -- Harnessed Icemaw Matriarch
(30470,56839,0,0,0,1,0,0,0), -- Skybreaker Cloudbuster
(30564,57401,0,0,0,1,0,0,0), -- Njorndar Proto-Drake
(30585,57418,0,0,0,1,0,0,0), -- Hammerhead
(30645,57612,0,0,0,1,0,0,0), -- Water Terror
(33217,62774,0,0,0,1,0,0,0), -- Stormwind Steed
(33319,62782,0,0,0,1,0,0,0), -- Darnassian Nightsaber
(33321,62784,0,0,0,1,0,0,0), -- Darkspear Raptor
(33519,63163,0,0,0,1,0,0,0), -- Black Knight's Gryphon
(33844,63791,0,0,0,1,0,0,0), -- Sunreaver Hawkstrider
(33845,63792,0,0,0,1,0,0,0), -- Quel'dorei Steed
(39714,74205,0,0,0,1,0,0,0); -- Shooting Mechano-Tank
+45
View File
@@ -16456,6 +16456,51 @@ bool Unit::CheckPlayerCondition(Player* pPlayer)
}
}
bool Unit::HandleSpellClick(Unit* clicker, int8 seatId)
{
bool success = false;
uint32 spellClickEntry = GetTypeId() == TYPEID_UNIT ? GetEntry() : GetUInt32Value(UNIT_FIELD_MOUNTDISPLAYID);
SpellClickInfoMapBounds clickPair = sObjectMgr->GetSpellClickInfoMapBounds(spellClickEntry);
for (SpellClickInfoMap::const_iterator itr = clickPair.first; itr != clickPair.second; ++itr)
{
if (itr->second.IsFitToRequirements(clicker, this))
{
Unit *caster = (itr->second.castFlags & NPC_CLICK_CAST_CASTER_CLICKER) ? clicker : this;
Unit *target = (itr->second.castFlags & NPC_CLICK_CAST_TARGET_CLICKER) ? clicker : this;
uint64 origCasterGUID = (itr->second.castFlags & NPC_CLICK_CAST_ORIG_CASTER_OWNER) ? GetOwnerGUID() : clicker->GetGUID();
SpellEntry const* spellEntry = sSpellStore.LookupEntry(itr->second.spellId);
// if(!spellEntry) should be checked at npc_spellclick load
if (seatId > -1)
{
uint8 i = 0;
bool valid = false;
while (i < MAX_SPELL_EFFECTS && !valid)
if (spellEntry->EffectApplyAuraName[i] == SPELL_AURA_CONTROL_VEHICLE)
valid = true;
if (!valid)
{
sLog->outErrorDb("Spell %u specified in npc_spellclick_spells is not a valid vehicle enter aura!", itr->second.spellId);
return false;
}
caster->CastCustomSpell(itr->second.spellId, SpellValueMod(SPELLVALUE_BASE_POINT0+i), seatId+1, target, true, NULL, NULL, origCasterGUID);
}
else
caster->CastSpell(target, spellEntry, true, NULL, NULL, origCasterGUID);
success = true;
}
}
if (this->ToCreature())
this->ToCreature()->AI()->DoAction(EVENT_SPELLCLICK);
return success;
}
void Unit::EnterVehicle(Vehicle *vehicle, int8 seatId, AuraApplication const * aurApp)
{
if (!isAlive() || GetVehicleKit() == vehicle || vehicle->GetBase()->IsOnVehicle(this))
+1
View File
@@ -2057,6 +2057,7 @@ class Unit : public WorldObject
bool m_ControlledByPlayer;
bool CheckPlayerCondition(Player* pPlayer);
bool HandleSpellClick(Unit* clicker, int8 seatId = -1);
void EnterVehicle(Unit *base, int8 seatId = -1, AuraApplication const * aurApp = NULL) { EnterVehicle(base->GetVehicleKit(), seatId, aurApp); }
void EnterVehicle(Vehicle *vehicle, int8 seatId = -1, AuraApplication const * aurApp = NULL);
void ExitVehicle(Position const* exitPosition = NULL);
+9 -1
View File
@@ -282,7 +282,14 @@ void Vehicle::InstallAccessory(uint32 entry, int8 seatId, bool minion, uint8 typ
if (minion)
accessory->AddUnitTypeMask(UNIT_MASK_ACCESSORY);
accessory->EnterVehicle(this, seatId);
if (!me->HandleSpellClick(accessory, seatId))
{
sLog->outErrorDb("Vehicle entry %u in vehicle_accessory does not have a valid record in npc_spellclick_spells! Calling default EnterVehicle()",
me->GetTypeId() == TYPEID_UNIT ? me->GetEntry() : me->GetUInt32Value(UNIT_FIELD_MOUNTDISPLAYID));
accessory->EnterVehicle(this, seatId);
}
// This is not good, we have to send update twice
accessory->SendMovementFlagUpdate();
@@ -358,6 +365,7 @@ bool Vehicle::AddPassenger(Unit *unit, int8 seatId)
if (!me->SetCharmedBy(unit, CHARM_TYPE_VEHICLE))
ASSERT(false);
// hack: should be done by aura system
if (VehicleScalingInfo const *scalingInfo = sObjectMgr->GetVehicleScalingInfo(m_vehicleInfo->m_ID))
{
Player *plr = unit->ToPlayer();
+33 -31
View File
@@ -195,49 +195,57 @@ LanguageDesc const* GetLanguageDescByID(uint32 lang)
return NULL;
}
bool SpellClickInfo::IsFitToRequirements(Player const* player, Creature const * clickNpc) const
bool SpellClickInfo::IsFitToRequirements(Unit const* clicker, Unit const* clickee) const
{
if (questStart)
Player const* playerClicker = NULL;
if (playerClicker = clicker->ToPlayer())
{
// not in expected required quest state
if (!player || ((!questStartCanActive || !player->IsActiveQuest(questStart)) && !player->GetQuestRewardStatus(questStart)))
return false;
}
if (questStart)
{
// not in expected required quest state
if (((!questStartCanActive || !playerClicker->IsActiveQuest(questStart)) && !playerClicker->GetQuestRewardStatus(questStart)))
return false;
}
if (questEnd)
{
// not in expected forbidden quest state
if (!player || player->GetQuestRewardStatus(questEnd))
return false;
if (questEnd)
{
// not in expected forbidden quest state
if (playerClicker->GetQuestRewardStatus(questEnd))
return false;
}
}
if (auraRequired)
if (!player->HasAura(auraRequired))
if (!clicker->HasAura(auraRequired))
return false;
if (auraForbidden)
if (player->HasAura(auraForbidden))
if (clicker->HasAura(auraForbidden))
return false;
Unit const * summoner = NULL;
// Check summoners for party
if (clickNpc->isSummon())
summoner = clickNpc->ToTempSummon()->GetSummoner();
if (clickee->isSummon())
summoner = clickee->ToTempSummon()->GetSummoner();
if (!summoner)
summoner = clickNpc;
summoner = clickee;
if (!playerClicker)
return true;
// This only applies to players
switch (userType)
{
case SPELL_CLICK_USER_FRIEND:
if (!player->IsFriendlyTo(summoner))
if (!playerClicker->IsFriendlyTo(summoner))
return false;
break;
case SPELL_CLICK_USER_RAID:
if (!player->IsInRaidWith(summoner))
if (!playerClicker->IsInRaidWith(summoner))
return false;
break;
case SPELL_CLICK_USER_PARTY:
if (!player->IsInPartyWith(summoner))
if (!playerClicker->IsInPartyWith(summoner))
return false;
break;
default:
@@ -2749,12 +2757,12 @@ void ObjectMgr::LoadVehicleAccessories()
{
Field *fields = result->Fetch();
uint32 uiEntry = fields[0].GetUInt32();
uint32 uiAccessory = fields[1].GetUInt32();
int8 uiSeat = int8(fields[2].GetInt16());
bool bMinion = fields[3].GetBool();
uint8 uiSummonType = fields[4].GetUInt8();
uint32 uiSummonTimer = fields[5].GetUInt32();
uint32 uiEntry = fields[0].GetUInt32();
uint32 uiAccessory = fields[1].GetUInt32();
int8 uiSeat = int8(fields[2].GetInt16());
bool bMinion = fields[3].GetBool();
uint8 uiSummonType = fields[4].GetUInt8();
uint32 uiSummonTimer= fields[5].GetUInt32();
if (!sCreatureStorage.LookupEntry<CreatureInfo>(uiEntry))
{
@@ -7622,9 +7630,6 @@ void ObjectMgr::LoadNPCSpellClickSpells()
continue;
}
if (!(cInfo->npcflag & UNIT_NPC_FLAG_SPELLCLICK))
const_cast<CreatureInfo*>(cInfo)->npcflag |= UNIT_NPC_FLAG_SPELLCLICK;
uint32 spellid = fields[1].GetUInt32();
SpellEntry const *spellinfo = sSpellStore.LookupEntry(spellid);
if (!spellinfo)
@@ -7696,9 +7701,6 @@ void ObjectMgr::LoadNPCSpellClickSpells()
info.userType = SpellClickUserTypes(userType);
mSpellClickInfoMap.insert(SpellClickInfoMap::value_type(npc_entry, info));
// mark creature template as spell clickable
const_cast<CreatureInfo*>(cInfo)->npcflag |= UNIT_NPC_FLAG_SPELLCLICK;
++count;
}
while (result->NextRow());
+1 -1
View File
@@ -335,7 +335,7 @@ struct SpellClickInfo
SpellClickUserTypes userType;
// helpers
bool IsFitToRequirements(Player const* player, Creature const * clickNpc) const;
bool IsFitToRequirements(Unit const* clicker, Unit const * clickee) const;
};
typedef std::multimap<uint32, SpellClickInfo> SpellClickInfoMap;
@@ -553,9 +553,12 @@ enum SpellClickUserTypes
SPELL_CLICK_USER_MAX = 4
};
#define NPC_CLICK_CAST_CASTER_PLAYER 0x01
#define NPC_CLICK_CAST_TARGET_PLAYER 0x02
#define NPC_CLICK_CAST_ORIG_CASTER_OWNER 0x04
enum SpellClickCastFlags
{
NPC_CLICK_CAST_CASTER_CLICKER = 0x01,
NPC_CLICK_CAST_TARGET_CLICKER = 0x02,
NPC_CLICK_CAST_ORIG_CASTER_OWNER = 0x04,
};
enum SheathTypes
{
@@ -559,25 +559,8 @@ void WorldSession::HandleSpellClick(WorldPacket & recv_data)
if (!unit->IsInWorld())
return;
SpellClickInfoMapBounds clickPair = sObjectMgr->GetSpellClickInfoMapBounds(unit->GetEntry());
for (SpellClickInfoMap::const_iterator itr = clickPair.first; itr != clickPair.second; ++itr)
{
if (itr->second.IsFitToRequirements(_player, unit))
{
Unit *caster = (itr->second.castFlags & NPC_CLICK_CAST_CASTER_PLAYER) ? (Unit*)_player : (Unit*)unit;
Unit *target = (itr->second.castFlags & NPC_CLICK_CAST_TARGET_PLAYER) ? (Unit*)_player : (Unit*)unit;
uint64 origCasterGUID = (itr->second.castFlags & NPC_CLICK_CAST_ORIG_CASTER_OWNER) ? unit->GetOwnerGUID() : 0;
caster->CastSpell(target, itr->second.spellId, true, NULL, NULL, origCasterGUID);
}
}
if (unit->IsVehicle())
{
if (unit->CheckPlayerCondition(_player))
_player->EnterVehicle(unit);
}
unit->AI()->DoAction(EVENT_SPELLCLICK);
if (!unit->HandleSpellClick(_player))
sLog->outErrorDb("Missing npc_spellclick_spells data for creature %u", unit->GetEntry());
}
void WorldSession::HandleMirrrorImageDataRequest(WorldPacket & recv_data)
+14 -3
View File
@@ -3129,7 +3129,7 @@ void Spell::EffectSummonType(SpellEffIndex effIndex)
{
float x, y, z;
m_caster->GetClosePoint(x, y, z, DEFAULT_WORLD_OBJECT_SIZE);
summon = m_caster->GetMap()->SummonCreature(entry, pos, properties, duration, m_caster);
summon = m_originalCaster->GetMap()->SummonCreature(entry, pos, properties, duration, m_caster);
if (!summon || !summon->IsVehicle())
return;
@@ -3137,10 +3137,21 @@ void Spell::EffectSummonType(SpellEffIndex effIndex)
{
SpellEntry const *spellProto = sSpellStore.LookupEntry(SpellMgr::CalculateSpellEffectAmount(m_spellInfo, effIndex));
if (spellProto)
m_caster->CastSpell(summon, spellProto, true);
{
m_originalCaster->CastSpell(summon, spellProto, true);
return;
}
}
m_caster->EnterVehicle(summon->GetVehicleKit());
// Hard coded enter vehicle spell
m_originalCaster->CastSpell(summon, 46598, true);
summon->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id);
uint32 faction = properties->Faction;
if (!faction)
faction = m_originalCaster->getFaction();
summon->setFaction(faction);
break;
}
}