Add support for vehicle scaling based on item level.
Requires database data. Fixes issue #2754 --HG-- branch : trunk
This commit is contained in:
@@ -15801,6 +15801,31 @@ LOCK TABLES `vehicle_accessory` WRITE;
|
||||
/*!40000 ALTER TABLE `vehicle_accessory` DISABLE KEYS */;
|
||||
/*!40000 ALTER TABLE `vehicle_accessory` ENABLE KEYS */;
|
||||
UNLOCK TABLES;
|
||||
|
||||
--
|
||||
-- Table structure for table `vehicle_scaling_info`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `vehicle_scaling_info`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8 */;
|
||||
CREATE TABLE `vehicle_scaling_info` (
|
||||
`entry` mediumint(8) unsigned NOT NULL default '0',
|
||||
`baseItemLevel` float NOT NULL default '0',
|
||||
`scalingFactor` float NOT NULL default '0',
|
||||
PRIMARY KEY (`entry`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
-- Dumping data for table `vehicle_scaling_info`
|
||||
--
|
||||
|
||||
LOCK TABLES `vehicle_scaling_info` WRITE;
|
||||
/*!40000 ALTER TABLE `vehicle_scaling_info` DISABLE KEYS */;
|
||||
/*!40000 ALTER TABLE `vehicle_scaling_info` ENABLE KEYS */;
|
||||
UNLOCK TABLES;
|
||||
|
||||
--
|
||||
-- Table structure for table `version`
|
||||
--
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
DROP TABLE IF EXISTS `vehicle_scaling_info`;
|
||||
CREATE TABLE `vehicle_scaling_info` (
|
||||
`entry` mediumint(8) unsigned NOT NULL default '0',
|
||||
`baseItemLevel` float NOT NULL default '0',
|
||||
`scalingFactor` float NOT NULL default '0',
|
||||
PRIMARY KEY (`entry`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED;
|
||||
@@ -703,6 +703,29 @@ struct ItemPrototype
|
||||
return 0;
|
||||
}
|
||||
|
||||
float GetItemLevelIncludingQuality() const
|
||||
{
|
||||
float itemLevel = (float)ItemLevel;
|
||||
switch (Quality)
|
||||
{
|
||||
case ITEM_QUALITY_POOR:
|
||||
case ITEM_QUALITY_NORMAL:
|
||||
case ITEM_QUALITY_UNCOMMON:
|
||||
case ITEM_QUALITY_ARTIFACT:
|
||||
case ITEM_QUALITY_HEIRLOOM:
|
||||
itemLevel -= 13; // leaving this as a separate statement since we do not know the real behavior in this case
|
||||
break;
|
||||
case ITEM_QUALITY_RARE:
|
||||
itemLevel -= 13;
|
||||
break;
|
||||
case ITEM_QUALITY_EPIC:
|
||||
case ITEM_QUALITY_LEGENDARY:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return itemLevel;
|
||||
}
|
||||
|
||||
bool IsPotion() const { return Class == ITEM_CLASS_CONSUMABLE && SubClass == ITEM_SUBCLASS_POTION; }
|
||||
bool IsWeaponVellum() const { return Class == ITEM_CLASS_TRADE_GOODS && SubClass == ITEM_SUBCLASS_WEAPON_ENCHANTMENT; }
|
||||
bool IsArmorVellum() const { return Class == ITEM_CLASS_TRADE_GOODS && SubClass == ITEM_SUBCLASS_ARMOR_ENCHANTMENT; }
|
||||
|
||||
@@ -13577,22 +13577,6 @@ void Player::PrepareGossipMenu(WorldObject *pSource, uint32 menuId, bool showQue
|
||||
pMenu->GetGossipMenu().AddGossipMenuItemData(itr->second.action_menu_id, itr->second.action_poi_id, itr->second.action_script_id);
|
||||
}
|
||||
}
|
||||
|
||||
// some gossips aren't handled in normal way ... so we need to do it this way .. TODO: handle it in normal way ;-)
|
||||
/*if (pMenu->Empty())
|
||||
{
|
||||
if (pCreature->HasFlag(UNIT_NPC_FLAGS,UNIT_NPC_FLAG_TRAINER))
|
||||
{
|
||||
// output error message if need
|
||||
pCreature->isCanTrainingOf(this, true);
|
||||
}
|
||||
|
||||
if (pCreature->HasFlag(UNIT_NPC_FLAGS,UNIT_NPC_FLAG_BATTLEMASTER))
|
||||
{
|
||||
// output error message if need
|
||||
pCreature->isCanInteractWithBattleMaster(this, true);
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
void Player::SendPreparedGossip(WorldObject *pSource)
|
||||
@@ -24137,7 +24121,7 @@ void Player::_LoadRandomBGStatus(QueryResult_AutoPtr result)
|
||||
|
||||
float Player::GetAverageItemLevel()
|
||||
{
|
||||
uint32 sum = 0;
|
||||
float sum = 0;
|
||||
uint32 count = 0;
|
||||
|
||||
for (int i = EQUIPMENT_SLOT_START; i < EQUIPMENT_SLOT_END; ++i)
|
||||
@@ -24147,7 +24131,7 @@ float Player::GetAverageItemLevel()
|
||||
continue;
|
||||
|
||||
if (m_items[i] && m_items[i]->GetProto())
|
||||
sum += m_items[i]->GetProto()->ItemLevel;
|
||||
sum += m_items[i]->GetProto()->GetItemLevelIncludingQuality();
|
||||
|
||||
count++;
|
||||
}
|
||||
|
||||
@@ -238,7 +238,7 @@ typedef std::list<PlayerCreateInfoAction> PlayerCreateInfoActions;
|
||||
|
||||
struct PlayerInfo
|
||||
{
|
||||
// existence checked by displayId != 0 // existence checked by displayId != 0
|
||||
// existence checked by displayId != 0
|
||||
PlayerInfo() : displayId_m(0),displayId_f(0),levelInfo(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -44,7 +44,7 @@ enum SocialFlag
|
||||
SOCIAL_FLAG_FRIEND = 0x01,
|
||||
SOCIAL_FLAG_IGNORED = 0x02,
|
||||
SOCIAL_FLAG_MUTED = 0x04, // guessed
|
||||
SOCIAL_FLAG_RAF = 0x08 // Recruit A Friend
|
||||
SOCIAL_FLAG_UNK = 0x08 // Unknown - does not appear to be RaF
|
||||
};
|
||||
|
||||
struct FriendInfo
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
#include "CreatureAI.h"
|
||||
#include "ZoneScript.h"
|
||||
|
||||
Vehicle::Vehicle(Unit *unit, VehicleEntry const *vehInfo) : me(unit), m_vehicleInfo(vehInfo), m_usableSeatNum(0)
|
||||
Vehicle::Vehicle(Unit *unit, VehicleEntry const *vehInfo) : me(unit), m_vehicleInfo(vehInfo), m_usableSeatNum(0), m_bonusHP(0)
|
||||
{
|
||||
for (uint32 i = 0; i < 8; ++i)
|
||||
{
|
||||
@@ -306,8 +306,6 @@ bool Vehicle::AddPassenger(Unit *unit, int8 seatId)
|
||||
if (seat->second.seatInfo->m_flags && !(seat->second.seatInfo->m_flags & 0x400))
|
||||
unit->addUnitState(UNIT_STAT_ONVEHICLE);
|
||||
|
||||
//SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PLAYER_CONTROLLED);
|
||||
|
||||
unit->AddUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT);
|
||||
VehicleSeatEntry const *veSeat = seat->second.seatInfo;
|
||||
unit->m_movementInfo.t_pos.m_positionX = veSeat->m_attachmentOffsetX;
|
||||
@@ -320,9 +318,24 @@ bool Vehicle::AddPassenger(Unit *unit, int8 seatId)
|
||||
if (me->GetTypeId() == TYPEID_UNIT
|
||||
&& unit->GetTypeId() == TYPEID_PLAYER
|
||||
&& seat->first == 0 && seat->second.seatInfo->m_flags & 0x800) // not right
|
||||
{
|
||||
if (!me->SetCharmedBy(unit, CHARM_TYPE_VEHICLE))
|
||||
ASSERT(false);
|
||||
|
||||
if (VehicleScalingInfo const *scalingInfo = sObjectMgr.GetVehicleScalingInfo(m_vehicleInfo->m_ID))
|
||||
{
|
||||
Player *plr = unit->ToPlayer();
|
||||
float averageItemLevel = plr->GetAverageItemLevel();
|
||||
if (averageItemLevel < scalingInfo->baseItemLevel)
|
||||
averageItemLevel = scalingInfo->baseItemLevel;
|
||||
averageItemLevel -= scalingInfo->baseItemLevel;
|
||||
|
||||
m_bonusHP = uint32(me->GetMaxHealth() * (averageItemLevel * scalingInfo->scalingFactor));
|
||||
me->SetMaxHealth(me->GetMaxHealth() + m_bonusHP);
|
||||
me->SetHealth(me->GetHealth() + m_bonusHP);
|
||||
}
|
||||
}
|
||||
|
||||
if (me->IsInWorld())
|
||||
{
|
||||
unit->SendMonsterMoveTransport(me);
|
||||
@@ -377,8 +390,17 @@ void Vehicle::RemovePassenger(Unit *unit)
|
||||
if (me->GetTypeId() == TYPEID_UNIT
|
||||
&& unit->GetTypeId() == TYPEID_PLAYER
|
||||
&& seat->first == 0 && seat->second.seatInfo->m_flags & 0x800)
|
||||
{
|
||||
me->RemoveCharmedBy(unit);
|
||||
|
||||
if (m_bonusHP)
|
||||
{
|
||||
me->SetHealth(me->GetHealth() - m_bonusHP);
|
||||
me->SetMaxHealth(me->GetMaxHealth() - m_bonusHP);
|
||||
m_bonusHP = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (me->GetTypeId() == TYPEID_UNIT && me->ToCreature()->IsAIEnabled)
|
||||
me->ToCreature()->AI()->PassengerBoarded(unit, seat->first, false);
|
||||
|
||||
|
||||
@@ -46,8 +46,16 @@ struct VehicleAccessory
|
||||
uint32 bMinion;
|
||||
};
|
||||
|
||||
struct VehicleScalingInfo
|
||||
{
|
||||
uint32 ID;
|
||||
float baseItemLevel;
|
||||
float scalingFactor;
|
||||
};
|
||||
|
||||
typedef std::vector<VehicleAccessory> VehicleAccessoryList;
|
||||
typedef std::map<uint32, VehicleAccessoryList> VehicleAccessoryMap;
|
||||
typedef std::map<uint32, VehicleScalingInfo> VehicleScalingMap;
|
||||
|
||||
typedef std::map<int8, VehicleSeat> SeatMap;
|
||||
|
||||
@@ -82,6 +90,7 @@ class Vehicle
|
||||
Unit *me;
|
||||
VehicleEntry const *m_vehicleInfo;
|
||||
uint32 m_usableSeatNum;
|
||||
uint32 m_bonusHP;
|
||||
|
||||
void InstallAccessory(uint32 entry, int8 seatId, bool minion = true);
|
||||
};
|
||||
|
||||
@@ -2647,6 +2647,51 @@ void ObjectMgr::LoadVehicleAccessories()
|
||||
sLog.outString(">> Loaded %u Vehicle Accessories", count);
|
||||
}
|
||||
|
||||
void ObjectMgr::LoadVehicleScaling()
|
||||
{
|
||||
m_VehicleScalingMap.clear(); // needed for reload case
|
||||
|
||||
uint32 count = 0;
|
||||
|
||||
QueryResult_AutoPtr result = WorldDatabase.Query("SELECT `entry`,`baseItemLevel`,`scalingFactor` FROM `vehicle_scaling_info`");
|
||||
|
||||
if (!result)
|
||||
{
|
||||
barGoLink bar(1);
|
||||
bar.step();
|
||||
sLog.outString();
|
||||
sLog.outErrorDb(">> Loaded 0 vehicle scaling entries. DB table `vehicle_scaling_info` is empty.");
|
||||
return;
|
||||
}
|
||||
|
||||
barGoLink bar(result->GetRowCount());
|
||||
|
||||
do
|
||||
{
|
||||
Field *fields = result->Fetch();
|
||||
bar.step();
|
||||
|
||||
uint32 vehicleEntry = fields[0].GetUInt32();
|
||||
float baseItemLevel = fields[1].GetFloat();
|
||||
float scalingFactor = fields[2].GetFloat();
|
||||
|
||||
if (!sVehicleStore.LookupEntry(vehicleEntry))
|
||||
{
|
||||
sLog.outErrorDb("Table `vehicle_scaling_info`: vehicle entry %u does not exist.", vehicleEntry);
|
||||
continue;
|
||||
}
|
||||
|
||||
m_VehicleScalingMap[vehicleEntry].ID = vehicleEntry;
|
||||
m_VehicleScalingMap[vehicleEntry].baseItemLevel = baseItemLevel;
|
||||
m_VehicleScalingMap[vehicleEntry].scalingFactor = scalingFactor;
|
||||
|
||||
++count;
|
||||
} while (result->NextRow());
|
||||
|
||||
sLog.outString();
|
||||
sLog.outString(">> Loaded %u vehicle scaling entries.", count);
|
||||
}
|
||||
|
||||
void ObjectMgr::LoadPetLevelInfo()
|
||||
{
|
||||
// Loading levels data
|
||||
|
||||
@@ -599,6 +599,14 @@ class ObjectMgr
|
||||
return NULL;
|
||||
}
|
||||
|
||||
VehicleScalingInfo const* GetVehicleScalingInfo(uint32 vehicleEntry) const
|
||||
{
|
||||
VehicleScalingMap::const_iterator itr = m_VehicleScalingMap.find(vehicleEntry);
|
||||
if (itr != m_VehicleScalingMap.end())
|
||||
return &itr->second;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void LoadGuilds();
|
||||
void LoadArenaTeams();
|
||||
void LoadGroups();
|
||||
@@ -665,6 +673,7 @@ class ObjectMgr
|
||||
void LoadInstanceTemplate();
|
||||
void LoadMailLevelRewards();
|
||||
void LoadVehicleAccessories();
|
||||
void LoadVehicleScaling();
|
||||
|
||||
void LoadGossipText();
|
||||
|
||||
@@ -1056,6 +1065,7 @@ class ObjectMgr
|
||||
ItemRequiredTargetMap m_ItemRequiredTarget;
|
||||
|
||||
VehicleAccessoryMap m_VehicleAccessoryMap;
|
||||
VehicleScalingMap m_VehicleScalingMap;
|
||||
|
||||
typedef std::vector<LocaleConstant> LocalForIndex;
|
||||
LocalForIndex m_LocalForIndex;
|
||||
|
||||
@@ -1359,6 +1359,9 @@ void World::SetInitialWorldSettings()
|
||||
sLog.outString("Loading Creature templates...");
|
||||
sObjectMgr.LoadCreatureTemplates();
|
||||
|
||||
sLog.outString("Loading Vehicle scaling information...");
|
||||
sObjectMgr.LoadVehicleScaling();
|
||||
|
||||
sLog.outString("Loading Reputation Reward Rates...");
|
||||
sObjectMgr.LoadReputationRewardRate();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user