mirror of
https://github.com/araxiaonline/pandaria_5.4.8.git
synced 2026-06-13 03:22:21 -04:00
Implemented creature sparring system
Big thanks: @Ovahlord - original script @ReyDonovan - port
This commit is contained in:
13
sql/updates/world/2022_01_20_00_world_creature_sparring.sql
Normal file
13
sql/updates/world/2022_01_20_00_world_creature_sparring.sql
Normal file
@@ -0,0 +1,13 @@
|
||||
DROP TABLE IF EXISTS `creature_sparring_template`;
|
||||
CREATE TABLE `creature_sparring_template` (
|
||||
`creature_id` mediumint(8) unsigned NOT NULL,
|
||||
`health_limit_pct` float DEFAULT "0",
|
||||
`comment` varchar(255) DEFAULT "",
|
||||
PRIMARY KEY (`creature_id`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
|
||||
|
||||
DELETE FROM `creature_sparring_template` WHERE `creature_id` IN (49422, 49423, 49428);
|
||||
INSERT INTO `creature_sparring_template`(`creature_id`, `health_limit_pct`, `comment`) VALUES
|
||||
(49422,85,"Rotbrain Berserker"),
|
||||
(49423,85,"Rotbrain Magus"),
|
||||
(49428,85,"Deathguard Protector");
|
||||
@@ -2947,3 +2947,8 @@ void Creature::RecalculateDynamicHealth(uint32 newHealth)
|
||||
SetHealth(newHealth - damage);
|
||||
}
|
||||
}
|
||||
|
||||
float Creature::GetSparringHealthLimit() const
|
||||
{
|
||||
return sObjectMgr->GetSparringHealthLimitFor(GetEntry());
|
||||
}
|
||||
|
||||
@@ -565,6 +565,8 @@ class Creature : public Unit, public GridObject<Creature>, public MapObject
|
||||
CreatureData const* GetCreatureData() const { return m_creatureData; }
|
||||
CreatureAddon const* GetCreatureAddon() const;
|
||||
|
||||
float GetSparringHealthLimit() const;
|
||||
|
||||
std::string GetAIName() const;
|
||||
std::string GetScriptName() const;
|
||||
uint32 GetScriptId() const;
|
||||
@@ -832,4 +834,6 @@ class ForcedDespawnDelayEvent : public BasicEvent
|
||||
Creature& m_owner;
|
||||
};
|
||||
|
||||
typedef std::unordered_map<uint32, float /*SparringHealthLimit*/> CreatureSparringTemplateMap;
|
||||
|
||||
#endif
|
||||
|
||||
@@ -783,6 +783,22 @@ void Unit::DealDamageMods(Unit* victim, uint32 &damage, uint32* absorb)
|
||||
|
||||
uint32 Unit::DealDamage(Unit* victim, uint32 damage, CleanDamage const* cleanDamage, DamageEffectType damagetype, SpellSchoolMask damageSchoolMask, SpellInfo const* spellProto, bool durabilityLoss)
|
||||
{
|
||||
if (Creature* target = victim->ToCreature())
|
||||
{
|
||||
if (GetTypeId() == TYPEID_UNIT && !IsCharmedOwnedByPlayerOrPlayer())
|
||||
{
|
||||
float sparringLimitPct = target->GetSparringHealthLimit();
|
||||
|
||||
if (sparringLimitPct != 0.0f)
|
||||
{
|
||||
if (damage >= target->GetHealth()) // First check: if we have a sparring limit we will never allow creatures to kill the sparring victim
|
||||
damage = target->GetHealth() - 1;
|
||||
else if (target->GetHealthPct() <= sparringLimitPct) // Second check: stop incomming damage when we have surpassed the health limit
|
||||
damage = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (GetTypeId() == TYPEID_PLAYER && ToPlayer()->GetSession()->GetSecurity() < SEC_GAMEMASTER && damage >= sWorld->getIntConfig(CONFIG_DAMAGE_LOG_MIN_DAMAGE))
|
||||
{
|
||||
float takenMod = victim->GetTotalAuraModifier(SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN);
|
||||
@@ -2221,6 +2237,22 @@ void Unit::CalcAbsorbResist(Unit* victim, SpellSchoolMask schoolMask, DamageEffe
|
||||
uint32 splitAbsorb = dmgInfo.GetAbsorbedSplit();
|
||||
DealDamageMods(caster, splitted, &splitAbsorb);
|
||||
|
||||
if (Creature* target = dmgInfo.GetVictim()->ToCreature())
|
||||
{
|
||||
if (GetTypeId() == TypeID::TYPEID_UNIT && !IsCharmedOwnedByPlayerOrPlayer())
|
||||
{
|
||||
float sparringLimitPct = target->GetSparringHealthLimit();
|
||||
|
||||
if (sparringLimitPct != 0.0f)
|
||||
{
|
||||
if (target->GetHealthPct() <= sparringLimitPct)
|
||||
{
|
||||
dmgInfo.ModifyDamage(dmgInfo.GetDamage() * -1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SendSpellNonMeleeDamageLog(caster, (*itr)->GetSpellInfo()->Id, splitted, schoolMask, splitAbsorb, 0, false, 0, false);
|
||||
|
||||
CleanDamage cleanDamage = CleanDamage(splitted, 0, BASE_ATTACK, MELEE_HIT_NORMAL);
|
||||
@@ -2359,6 +2391,23 @@ void Unit::AttackerStateUpdate(Unit* victim, bool ignoreLos, WeaponAttackType at
|
||||
CalculateMeleeDamage(victim, 0, &damageInfo, attType);
|
||||
// Send log damage message to client
|
||||
DealDamageMods(victim, damageInfo.damage, &damageInfo.absorb);
|
||||
|
||||
if (Creature* target = victim->ToCreature())
|
||||
{
|
||||
if (GetTypeId() == TypeID::TYPEID_UNIT && !IsCharmedOwnedByPlayerOrPlayer())
|
||||
{
|
||||
float sparringLimitPct = target->GetSparringHealthLimit();
|
||||
|
||||
if (sparringLimitPct != 0.0f)
|
||||
{
|
||||
if (target->GetHealthPct() <= sparringLimitPct)
|
||||
{
|
||||
damageInfo.HitInfo |= HITINFO_FAKE_DAMAGE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SendAttackStateUpdate(&damageInfo);
|
||||
DealMeleeDamage(&damageInfo, true);
|
||||
|
||||
|
||||
@@ -704,6 +704,51 @@ void ObjectMgr::LoadCreatureDifficultyModifiers()
|
||||
TC_LOG_INFO("server.loading", ">> Loaded %u creature difficulty modifiers in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
|
||||
}
|
||||
|
||||
void ObjectMgr::LoadCreatureSparringTemplate()
|
||||
{
|
||||
uint32 oldMSTime = getMSTime();
|
||||
|
||||
// 0 1
|
||||
QueryResult result = WorldDatabase.Query("SELECT creature_id, health_limit_pct FROM creature_sparring_template");
|
||||
|
||||
if (!result)
|
||||
{
|
||||
TC_LOG_INFO("server.loading", ">> Loaded 0 creature template sparring definitions. DB table `creature_sparring_template` is empty.");
|
||||
return;
|
||||
}
|
||||
|
||||
uint32 count = 0;
|
||||
do
|
||||
{
|
||||
Field* fields = result->Fetch();
|
||||
|
||||
uint32 entry = fields[0].GetUInt32();
|
||||
float healthPct = fields[1].GetFloat();
|
||||
|
||||
if (!sObjectMgr->GetCreatureTemplate(entry))
|
||||
{
|
||||
TC_LOG_ERROR("sql.sql", "Creature template (Entry: %u) does not exist but has a record in `creature_sparring_template`", entry);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (healthPct > 100.0f)
|
||||
{
|
||||
TC_LOG_ERROR("sql.sql", "Sparring entry (Entry: %u) exceeds the health percentage limit. Setting to 100.", entry);
|
||||
healthPct = 100.0f;
|
||||
}
|
||||
|
||||
if (healthPct <= 0.0f)
|
||||
{
|
||||
TC_LOG_ERROR("sql.sql", "Sparring entry (Entry: %u) has a negative or too small health percentage. Setting to 0.1.", entry);
|
||||
healthPct = 0.1f;
|
||||
}
|
||||
|
||||
_creatureSparringTemplateStore[entry] = healthPct;
|
||||
} while (result->NextRow());
|
||||
|
||||
TC_LOG_INFO("server.loading", ">> Loaded %u creature sparring templates in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
|
||||
}
|
||||
|
||||
void ObjectMgr::CheckCreatureTemplate(CreatureTemplate const* cInfo)
|
||||
{
|
||||
if (!cInfo)
|
||||
|
||||
@@ -1108,6 +1108,7 @@ class ObjectMgr
|
||||
void LoadGraveyardOrientations();
|
||||
void LoadCreatureTemplates();
|
||||
void LoadCreatureTemplateAddons();
|
||||
void LoadCreatureSparringTemplate();
|
||||
void LoadCreatureDifficultyModifiers();
|
||||
void CheckCreatureTemplate(CreatureTemplate const* cInfo);
|
||||
void LoadTempSummons();
|
||||
@@ -1378,8 +1379,20 @@ class ObjectMgr
|
||||
return &itr->second;
|
||||
}
|
||||
GameObjectData& NewGOData(uint32 guid) { return _gameObjectDataStore[guid]; }
|
||||
|
||||
void DeleteGOData(uint32 guid);
|
||||
|
||||
float GetSparringHealthLimitFor(uint32 entry) const
|
||||
{
|
||||
auto itr = _creatureSparringTemplateStore.find(entry);
|
||||
|
||||
if (itr != _creatureSparringTemplateStore.end())
|
||||
{
|
||||
return itr->second;
|
||||
}
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
TrinityStringLocale const* GetTrinityStringLocale(int32 entry) const
|
||||
{
|
||||
TrinityStringLocaleContainer::const_iterator itr = _trinityStringLocaleStore.find(entry);
|
||||
@@ -1792,6 +1805,7 @@ class ObjectMgr
|
||||
CreatureAddonContainer _creatureAddonStore;
|
||||
GameObjectAddonContainer _gameObjectAddonStore;
|
||||
CreatureAddonContainer _creatureTemplateAddonStore;
|
||||
CreatureSparringTemplateMap _creatureSparringTemplateStore;
|
||||
EquipmentInfoContainer _equipmentInfoStore;
|
||||
LinkedRespawnContainer _linkedRespawnStore;
|
||||
CreatureLocaleContainer _creatureLocaleStore;
|
||||
|
||||
@@ -2811,6 +2811,22 @@ void Spell::DoAllEffectOnTarget(TargetInfo* target)
|
||||
caster->CalculateSpellDamageTaken(&damageInfo, m_damage * m_spellValue->Multiplier, m_spellInfo, m_attackType, target->crit, procVictim, createProcExtendMask(&damageInfo, missInfo));
|
||||
caster->DealDamageMods(damageInfo.target, damageInfo.damage, &damageInfo.absorb);
|
||||
|
||||
if (Creature* target = damageInfo.target->ToCreature())
|
||||
{
|
||||
if (caster->GetTypeId() == TYPEID_UNIT && !caster->IsCharmedOwnedByPlayerOrPlayer())
|
||||
{
|
||||
float sparringLimitPct = target->GetSparringHealthLimit();
|
||||
|
||||
if (sparringLimitPct != 0.0f)
|
||||
{
|
||||
if (target->GetHealthPct() <= sparringLimitPct)
|
||||
{
|
||||
damageInfo.damage = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Send log damage message to client
|
||||
caster->SendSpellNonMeleeDamageLog(&damageInfo);
|
||||
caster->DealSpellDamage(&damageInfo, true);
|
||||
|
||||
@@ -568,7 +568,7 @@ void World::LoadConfigSettings(bool reload)
|
||||
m_bool_configs[CONFIG_ALLOW_TWO_SIDE_INTERACTION_GROUP] = sConfigMgr->GetBoolDefault("AllowTwoSide.Interaction.Group", false);
|
||||
m_bool_configs[CONFIG_ALLOW_TWO_SIDE_INTERACTION_GUILD] = sConfigMgr->GetBoolDefault("AllowTwoSide.Interaction.Guild", false);
|
||||
m_bool_configs[CONFIG_ALLOW_TWO_SIDE_INTERACTION_AUCTION] = sConfigMgr->GetBoolDefault("AllowTwoSide.Interaction.Auction", false);
|
||||
m_bool_configs[CONFIG_ALLOW_TWO_SIDE_TRADE] = sConfigMgr->GetBoolDefault("AllowTwoSide.trade", false);
|
||||
m_bool_configs[CONFIG_ALLOW_TWO_SIDE_TRADE] = sConfigMgr->GetBoolDefault("AllowTwoSide.Trade", false);
|
||||
m_int_configs[CONFIG_STRICT_PLAYER_NAMES] = sConfigMgr->GetIntDefault ("StrictPlayerNames", 0);
|
||||
m_int_configs[CONFIG_STRICT_CHARTER_NAMES] = sConfigMgr->GetIntDefault ("StrictCharterNames", 0);
|
||||
m_int_configs[CONFIG_STRICT_PET_NAMES] = sConfigMgr->GetIntDefault ("StrictPetNames", 0);
|
||||
@@ -1890,6 +1890,9 @@ void World::SetInitialWorldSettings()
|
||||
TC_LOG_INFO("server.loading", "Loading GameObject Addon Data...");
|
||||
sObjectMgr->LoadGameObjectAddons(); // must be after LoadGameObjectTemplate() and LoadGameobjects()
|
||||
|
||||
TC_LOG_INFO("server.loading", "Loading Creature Sparring Data...");
|
||||
sObjectMgr->LoadCreatureSparringTemplate();
|
||||
|
||||
TC_LOG_INFO("server.loading", "Loading Creature Linked Respawn...");
|
||||
sObjectMgr->LoadLinkedRespawn(); // must be after LoadCreatures(), LoadGameObjects()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user