mirror of
https://github.com/EQEmu/Server.git
synced 2026-06-26 07:17:16 +00:00
major updates
optimized pet support perl support
This commit is contained in:
@@ -45,6 +45,8 @@ enum : int { //values for pTimerType
|
|||||||
pTimerLinkedSpellReuseStart = 28,
|
pTimerLinkedSpellReuseStart = 28,
|
||||||
pTimerLinkedSpellReuseEnd = 48,
|
pTimerLinkedSpellReuseEnd = 48,
|
||||||
|
|
||||||
|
pTimerShieldAbility = 86,
|
||||||
|
|
||||||
pTimerLayHands = 87, //these IDs are used by client too
|
pTimerLayHands = 87, //these IDs are used by client too
|
||||||
pTimerHarmTouch = 89, //so dont change them
|
pTimerHarmTouch = 89, //so dont change them
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -572,7 +572,7 @@ typedef enum {
|
|||||||
#define SE_FleshToBone 207 // implemented
|
#define SE_FleshToBone 207 // implemented
|
||||||
//#define SE_PurgePoison 208 // not used
|
//#define SE_PurgePoison 208 // not used
|
||||||
#define SE_DispelBeneficial 209 // implemented
|
#define SE_DispelBeneficial 209 // implemented
|
||||||
//#define SE_PetShield 210 // *not implemented
|
#define SE_PetShield 210 // implmented, @Shiedling, allows pet to 'shield' owner for 50 pct of damage taken for a duration, base: 1 (Time multiplier 1=12 seconds, 2=24 ect), limit: mitigation on pet owner override (not on live), max: mitigation on pet overide (not on live)
|
||||||
#define SE_AEMelee 211 // implemented TO DO: Implement to allow NPC use (client only atm).
|
#define SE_AEMelee 211 // implemented TO DO: Implement to allow NPC use (client only atm).
|
||||||
#define SE_FrenziedDevastation 212 // implemented - increase spell criticals + all DD spells cast 2x mana.
|
#define SE_FrenziedDevastation 212 // implemented - increase spell criticals + all DD spells cast 2x mana.
|
||||||
#define SE_PetMaxHP 213 // implemented[AA] - increases the maximum hit points of your pet
|
#define SE_PetMaxHP 213 // implemented[AA] - increases the maximum hit points of your pet
|
||||||
|
|||||||
+19
-24
@@ -1691,6 +1691,7 @@ bool Client::Death(Mob* killerMob, int32 damage, uint16 spell, EQ::skills::Skill
|
|||||||
InterruptSpell();
|
InterruptSpell();
|
||||||
SetPet(0);
|
SetPet(0);
|
||||||
SetHorseId(0);
|
SetHorseId(0);
|
||||||
|
ShieldAbilityClearVariables();
|
||||||
dead = true;
|
dead = true;
|
||||||
|
|
||||||
if (GetMerc()) {
|
if (GetMerc()) {
|
||||||
@@ -2252,6 +2253,8 @@ bool NPC::Death(Mob* killer_mob, int32 damage, uint16 spell, EQ::skills::SkillTy
|
|||||||
Log(Logs::Detail, Logs::Attack, "%s Mobs currently Aggro %i", __FUNCTION__, zone->MobsAggroCount());
|
Log(Logs::Detail, Logs::Attack, "%s Mobs currently Aggro %i", __FUNCTION__, zone->MobsAggroCount());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ShieldAbilityClearVariables();
|
||||||
|
|
||||||
SetHP(0);
|
SetHP(0);
|
||||||
SetPet(0);
|
SetPet(0);
|
||||||
|
|
||||||
@@ -5278,61 +5281,53 @@ void Mob::CommonOutgoingHitSuccess(Mob* defender, DamageHitInfo &hit, ExtraAttac
|
|||||||
|
|
||||||
hit.damage_done += (hit.damage_done * pct_damage_reduction / 100) + (defender->GetFcDamageAmtIncoming(this, 0, true, hit.skill));
|
hit.damage_done += (hit.damage_done * pct_damage_reduction / 100) + (defender->GetFcDamageAmtIncoming(this, 0, true, hit.skill));
|
||||||
|
|
||||||
Shout("Shielder ID [%i]", defender->GetShielderID());
|
|
||||||
|
|
||||||
if (defender->GetShielderID()) {
|
if (defender->GetShielderID()) {
|
||||||
hit.damage_done = hit.damage_done * 50 / 100;//Don't round.
|
|
||||||
DoShieldDamageOnShielder(defender, hit.damage_done, hit.skill);
|
DoShieldDamageOnShielder(defender, hit.damage_done, hit.skill);
|
||||||
|
hit.damage_done -= hit.damage_done * defender->GetShieldTargetMitigation() / 100; //Default shielded takes 50 pct damage
|
||||||
}
|
}
|
||||||
|
|
||||||
CheckNumHitsRemaining(NumHit::OutgoingHitSuccess);
|
CheckNumHitsRemaining(NumHit::OutgoingHitSuccess);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Mob::DoShieldDamageOnShielder(Mob* shielder_target, int hit_damage_done, EQ::skills::SkillType skillInUse)
|
void Mob::DoShieldDamageOnShielder(Mob* shield_target, int hit_damage_done, EQ::skills::SkillType skillInUse)
|
||||||
{
|
{
|
||||||
if (!shielder_target) {
|
if (!shield_target) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Mob *shielder = entity_list.GetMob(shielder_target->GetShielderID());
|
Mob *shielder = entity_list.GetMob(shield_target->GetShielderID());
|
||||||
|
|
||||||
if (!shielder) {
|
if (!shielder) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//AA to increase SPA 230 extended shielding
|
if (shield_target->CalculateDistance(shielder->GetX(), shielder->GetY(), shielder->GetZ()) > static_cast<float>(shielder->GetMaxShielderDistance())) {
|
||||||
int max_shielder_distance = 15;
|
|
||||||
int distance_mod = aabonuses.ExtendedShielding + itembonuses.ExtendedShielding + spellbonuses.ExtendedShielding;
|
|
||||||
max_shielder_distance += max_shielder_distance * distance_mod / 100;
|
|
||||||
max_shielder_distance = std::max(max_shielder_distance, 0);
|
|
||||||
|
|
||||||
if (shielder_target->CalculateDistance(shielder->GetX(), shielder->GetY(), shielder->GetZ()) > static_cast<float>(max_shielder_distance)) {
|
|
||||||
//Clear variables Shield end
|
|
||||||
Shout("Clear variables shield end");
|
|
||||||
shielder->SetShieldTargetID(0);
|
shielder->SetShieldTargetID(0);
|
||||||
shielder_target->SetShielderID(0);
|
shielder->SetShielderMitigation(0);
|
||||||
|
shielder->SetShielerMaxDistance(0);
|
||||||
|
shielder->shield_timer.Disable();
|
||||||
|
shield_target->SetShielderID(0);
|
||||||
|
shield_target->SetShieldTargetMitigation(0);
|
||||||
return; //Too far away, no message is given thoughh.
|
return; //Too far away, no message is given thoughh.
|
||||||
}
|
}
|
||||||
|
|
||||||
int mitigation = 75;
|
int mitigation = shielder->GetShielderMitigation(); //Default shielder mitigates 25 pct of damage taken, this can be increased up to max 50 by equiping a shield item
|
||||||
|
|
||||||
if (shielder->HasShieldEquiped() && shielder->IsClient()) {
|
if (shielder->IsClient() && shielder->HasShieldEquiped()) {
|
||||||
|
|
||||||
EQ::ItemInstance* inst = CastToClient()->GetInv().GetItem(EQ::invslot::slotSecondary);
|
EQ::ItemInstance* inst = shielder->CastToClient()->GetInv().GetItem(EQ::invslot::slotSecondary);
|
||||||
|
|
||||||
if (inst) {
|
if (inst) {
|
||||||
|
|
||||||
const EQ::ItemData* shield = inst->GetItem();
|
const EQ::ItemData* shield = inst->GetItem();
|
||||||
if (shield && shield->ItemType == EQ::item::ItemTypeShield) {
|
if (shield && shield->ItemType == EQ::item::ItemTypeShield) {
|
||||||
mitigation -= shield->AC * 0.50; //1% increase per 2 AC
|
mitigation += shield->AC * 50 / 100; //1% increase per 2 AC
|
||||||
|
std::min(50, mitigation);//50 pct max mitigation bonus from /shield
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mitigation = std::max(mitigation, 50);
|
hit_damage_done -= hit_damage_done * mitigation / 100;
|
||||||
|
|
||||||
hit_damage_done = hit_damage_done * mitigation / 100;
|
|
||||||
|
|
||||||
shielder->Damage(this, hit_damage_done, SPELL_UNKNOWN, skillInUse, true, -1, false, m_specialattacks);
|
shielder->Damage(this, hit_damage_done, SPELL_UNKNOWN, skillInUse, true, -1, false, m_specialattacks);
|
||||||
shielder->CheckNumHitsRemaining(NumHit::OutgoingHitSuccess);
|
shielder->CheckNumHitsRemaining(NumHit::OutgoingHitSuccess);
|
||||||
}
|
}
|
||||||
|
|||||||
+45
-30
@@ -12804,14 +12804,30 @@ void Client::Handle_OP_SetTitle(const EQApplicationPacket *app)
|
|||||||
|
|
||||||
void Client::Handle_OP_Shielding(const EQApplicationPacket *app)
|
void Client::Handle_OP_Shielding(const EQApplicationPacket *app)
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
|
/shield command mechanics
|
||||||
|
Warriors get this skill at level 30
|
||||||
|
Used by typing /shield while targeting a player
|
||||||
|
While active for the duration of 12 seconds baseline. The 'shield target' will take 50 pct less damage and
|
||||||
|
the 'shielder' will be hit with the damage taken by the 'shield target' after all applicable mitigiont is calculated,
|
||||||
|
the damage on the 'shielder' will be reduced by 25 percent, this reduction can be increased to 50 pct if equiping a shield.
|
||||||
|
You receive a 1% increase in mitigation for every 2 AC on the shield.
|
||||||
|
Shielder must stay with in a close distance (15 units) to your 'shield target'. If either move out of range, shield ends, no message given.
|
||||||
|
Both duration and shield range can be modified by AA.
|
||||||
|
Recast is 3 minutes.
|
||||||
|
|
||||||
|
For custom use cases, Mob::ShieldAbility can be used in quests with all parameters being altered. This functional
|
||||||
|
is also used for SPA 201 SE_PetShield, which functions in a simalar manner with pet shielding owner.
|
||||||
|
|
||||||
|
Note: If either the shielder or the shield target die all variables are reset on both.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
if (app->size != sizeof(Shielding_Struct)) {
|
if (app->size != sizeof(Shielding_Struct)) {
|
||||||
LogError("OP size error: OP_Shielding expected:[{}] got:[{}]", sizeof(Shielding_Struct), app->size);
|
LogError("OP size error: OP_Shielding expected:[{}] got:[{}]", sizeof(Shielding_Struct), app->size);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO: Defensive makes it not cast?
|
|
||||||
//TODO: Bankers ect don't let you shjield 6826 You can not perform shielding while you are speaking with a banker, a merchant, or a guildmaster.
|
|
||||||
|
|
||||||
if (GetLevel() < 30) { //Client gives message
|
if (GetLevel() < 30) { //Client gives message
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -12820,20 +12836,24 @@ void Client::Handle_OP_Shielding(const EQApplicationPacket *app)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pTimerType timer = pTimerShieldAbility;
|
||||||
|
|
||||||
|
if (!p_timers.Expired(&database, timer, false)) {
|
||||||
|
uint32 remain = p_timers.GetRemainingTime(timer);
|
||||||
|
Message(Chat::White, "You can use the ability /shield in %d minutes %d seconds.", ((remain) / 60), (remain % 60));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
Shielding_Struct* shield = (Shielding_Struct*)app->pBuffer;
|
Shielding_Struct* shield = (Shielding_Struct*)app->pBuffer;
|
||||||
|
|
||||||
Mob* shield_target = entity_list.GetMob(shield->target_id);
|
Mob* shield_target = entity_list.GetMob(shield->target_id);
|
||||||
|
|
||||||
Shout("PACKET Shielder %i", shield_target->GetShielderID());
|
|
||||||
Shout("PACKET Shield Target %i", GetShieldTargetID());
|
|
||||||
|
|
||||||
if (!shield_target) {
|
if (!shield_target) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (shield_target->IsNPC()) {
|
if (shield_target->IsNPC()) {
|
||||||
//You must first target a living player //TODO Find string
|
MessageString(Chat::White, SHIELD_TARGET_NPC);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -12841,48 +12861,43 @@ void Client::Handle_OP_Shielding(const EQApplicationPacket *app)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Does 'Shield Target' already have a 'Shielder'
|
//You are a 'Shield Target' already have a 'Shielder'
|
||||||
if (shield_target->GetShielderID() == GetID()) {
|
if (GetShielderID() || shield_target->GetShielderID()) {
|
||||||
MessageString(Chat::White, ALREADY_SHIELDED);
|
MessageString(Chat::White, ALREADY_SHIELDED);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Does 'Shielder' already have a 'Shield Target'
|
//You are being shielded or already have a 'Shield Target'
|
||||||
if (GetShieldTargetID() == GetID()) {
|
if (GetShieldTargetID() || shield_target->GetShieldTargetID()) {
|
||||||
MessageString(Chat::White, ALREADY_SHIELDED);
|
MessageString(Chat::White, ALREADY_SHIELDING);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//AA to increase SPA 230 extended shielding
|
//AA to increase SPA 230 extended shielding
|
||||||
|
int max_shlder_distance = 15;
|
||||||
|
max_shlder_distance += aabonuses.ExtendedShielding + itembonuses.ExtendedShielding + spellbonuses.ExtendedShielding;
|
||||||
|
max_shlder_distance = std::max(max_shlder_distance, 0);
|
||||||
|
|
||||||
int max_shielder_distance = 15;
|
if (shield_target->CalculateDistance(GetX(), GetY(), GetZ()) > static_cast<float>(max_shlder_distance)) {
|
||||||
int distance_mod = aabonuses.ExtendedShielding + itembonuses.ExtendedShielding + spellbonuses.ExtendedShielding;
|
|
||||||
max_shielder_distance += max_shielder_distance * distance_mod / 100;
|
|
||||||
max_shielder_distance = std::max(max_shielder_distance, 0);
|
|
||||||
|
|
||||||
if (shield_target->CalculateDistance(GetX(), GetY(), GetZ()) > static_cast<float>(max_shielder_distance)) {
|
|
||||||
return; //Too far away, no message is given thoughh.
|
return; //Too far away, no message is given thoughh.
|
||||||
}
|
}
|
||||||
|
|
||||||
entity_list.MessageCloseString(this, false, 100, 0, START_SHIELDING, GetName(), shield_target->GetName());
|
entity_list.MessageCloseString(this, false, 100, 0, START_SHIELDING, GetName(), shield_target->GetName());
|
||||||
|
|
||||||
//Apply to Shielder
|
|
||||||
//shield_ability.shield_target_id = shield_target->GetID();
|
|
||||||
|
|
||||||
//Apply to Shield Target
|
|
||||||
//shield_target->shield_ability.shielder_id = GetID();
|
|
||||||
|
|
||||||
SetShieldTargetID(shield_target->GetID());
|
SetShieldTargetID(shield_target->GetID());
|
||||||
shield_target->SetShielderID(GetID());
|
SetShielderMitigation(25);
|
||||||
|
SetShielerMaxDistance(max_shlder_distance);
|
||||||
|
|
||||||
|
shield_target->SetShielderID(GetID());
|
||||||
|
shield_target->SetShieldTargetMitigation(50);
|
||||||
|
|
||||||
//Calculate AA for adding time SPA 255 extend shield duration
|
//Calculate AA for adding time SPA 255 extend shield duration
|
||||||
int shield_duration = 12000;
|
int shield_duration = 12000;
|
||||||
Shout("1 Duration %i", shield_duration);
|
|
||||||
shield_duration += (aabonuses.ShieldDuration + itembonuses.ShieldDuration + spellbonuses.ShieldDuration) * 1000;
|
shield_duration += (aabonuses.ShieldDuration + itembonuses.ShieldDuration + spellbonuses.ShieldDuration) * 1000;
|
||||||
Shout("2 Duration %i", shield_duration);
|
|
||||||
shield_duration = std::max(shield_duration, 1); //Incase of negative modifiers lets just make min duration 1 ms.
|
shield_duration = std::max(shield_duration, 1); //Incase of negative modifiers lets just make min duration 1 ms.
|
||||||
Shout("3 Duration %i", shield_duration);
|
shield_timer.Start(static_cast<uint32>(shield_duration));
|
||||||
shield_timer.Start(shield_duration);
|
|
||||||
|
p_timers.Start(timer, SHIELD_ABILITY_RECAST_TIME);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -461,14 +461,7 @@ bool Client::Process() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (shield_timer.Check()) {
|
if (shield_timer.Check()) {
|
||||||
Mob * shield_target = entity_list.GetMob(GetShieldTargetID());
|
ShieldAbilityFinish();
|
||||||
|
|
||||||
if (shield_target) {
|
|
||||||
entity_list.MessageCloseString(this, false, 100, 0, END_SHIELDING, GetCleanName(), shield_target->GetCleanName());
|
|
||||||
}
|
|
||||||
shield_timer.Disable();
|
|
||||||
SetShieldTargetID(0);
|
|
||||||
shield_target->SetShielderID(0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SpellProcess();
|
SpellProcess();
|
||||||
|
|||||||
+2
-1
@@ -105,6 +105,8 @@
|
|||||||
|
|
||||||
#define AURA_HARDCAP 2
|
#define AURA_HARDCAP 2
|
||||||
|
|
||||||
|
#define SHIELD_ABILITY_RECAST_TIME 180
|
||||||
|
|
||||||
typedef enum { //focus types
|
typedef enum { //focus types
|
||||||
focusSpellHaste = 1, //@Fc, SPA: 127, SE_IncreaseSpellHaste, On Caster, cast time mod pct, base: pct
|
focusSpellHaste = 1, //@Fc, SPA: 127, SE_IncreaseSpellHaste, On Caster, cast time mod pct, base: pct
|
||||||
focusSpellDuration, //@Fc, SPA: 128, SE_IncreaseSpellDuration, On Caster, spell duration mod pct, base: pct
|
focusSpellDuration, //@Fc, SPA: 128, SE_IncreaseSpellDuration, On Caster, spell duration mod pct, base: pct
|
||||||
@@ -544,7 +546,6 @@ struct StatBonuses {
|
|||||||
int32 Pet_Crit_Melee_Damage_Pct_Owner; // base = percent mod for pet critcal damage from owner
|
int32 Pet_Crit_Melee_Damage_Pct_Owner; // base = percent mod for pet critcal damage from owner
|
||||||
int32 Pet_Add_Atk; // base = Pet ATK bonus from owner
|
int32 Pet_Add_Atk; // base = Pet ATK bonus from owner
|
||||||
|
|
||||||
|
|
||||||
// AAs
|
// AAs
|
||||||
int32 ShieldDuration; // extends duration of /shield ability
|
int32 ShieldDuration; // extends duration of /shield ability
|
||||||
int32 ExtendedShielding; // extends range of /shield ability
|
int32 ExtendedShielding; // extends range of /shield ability
|
||||||
|
|||||||
+101
@@ -378,6 +378,9 @@ Mob::Mob(
|
|||||||
shield_timer.Disable();
|
shield_timer.Disable();
|
||||||
shield_target_id = 0;
|
shield_target_id = 0;
|
||||||
shielder_id = 0;
|
shielder_id = 0;
|
||||||
|
shield_target_mitigation = 0;
|
||||||
|
shielder_mitigation = 0;
|
||||||
|
shielder_max_distance = 0;
|
||||||
|
|
||||||
destructibleobject = false;
|
destructibleobject = false;
|
||||||
wandertype = 0;
|
wandertype = 0;
|
||||||
@@ -6118,6 +6121,104 @@ float Mob::GetDefaultRaceSize() const {
|
|||||||
return GetRaceGenderDefaultHeight(race, gender);
|
return GetRaceGenderDefaultHeight(race, gender);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Mob::ShieldAbility(uint32 target_id, int max_shlder_distance, int shield_duration, int shld_target_mitigation, int shlder_mitigation)
|
||||||
|
{
|
||||||
|
|
||||||
|
Mob* shield_target = entity_list.GetMob(target_id);
|
||||||
|
|
||||||
|
if (!shield_target) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (shield_target->GetID() == GetID()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//You have a shielder, or your 'Shield Target' already has a 'Shielder'
|
||||||
|
if (GetShielderID() || shield_target->GetShielderID()) {
|
||||||
|
|
||||||
|
if (IsClient()) {
|
||||||
|
MessageString(Chat::White, ALREADY_SHIELDED);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//You are being shielded or already have a 'Shield Target'
|
||||||
|
if (GetShieldTargetID() || shield_target->GetShieldTargetID()) {
|
||||||
|
|
||||||
|
if (IsClient()) {
|
||||||
|
MessageString(Chat::White, ALREADY_SHIELDING);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (shield_target->CalculateDistance(GetX(), GetY(), GetZ()) > static_cast<float>(max_shlder_distance)) {
|
||||||
|
if (IsClient()) {
|
||||||
|
MessageString(Chat::White, TARGET_TOO_FAR); //Live doesn't give any message for failure, for the quest ability lets allow it.
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
entity_list.MessageCloseString(this, false, 100, 0, START_SHIELDING, GetCleanName(), shield_target->GetCleanName());
|
||||||
|
|
||||||
|
SetShieldTargetID(shield_target->GetID());
|
||||||
|
SetShielderMitigation(shlder_mitigation);
|
||||||
|
SetShielerMaxDistance(max_shlder_distance);
|
||||||
|
|
||||||
|
shield_target->SetShielderID(GetID());
|
||||||
|
shield_target->SetShieldTargetMitigation(shld_target_mitigation);
|
||||||
|
|
||||||
|
shield_timer.Start(shield_duration);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Mob::ShieldAbilityFinish()
|
||||||
|
{
|
||||||
|
Mob* shield_target = entity_list.GetMob(GetShieldTargetID());
|
||||||
|
|
||||||
|
if (shield_target) {
|
||||||
|
entity_list.MessageCloseString(this, false, 100, 0, END_SHIELDING, GetCleanName(), shield_target->GetCleanName());
|
||||||
|
shield_target->SetShielderID(0);
|
||||||
|
shield_target->SetShieldTargetMitigation(0);
|
||||||
|
}
|
||||||
|
SetShieldTargetID(0);
|
||||||
|
SetShielderMitigation(0);
|
||||||
|
SetShielerMaxDistance(0);
|
||||||
|
shield_timer.Disable();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Mob::ShieldAbilityClearVariables()
|
||||||
|
{
|
||||||
|
//If 'shield target' dies
|
||||||
|
if (GetShielderID()){
|
||||||
|
|
||||||
|
Mob* shielder = entity_list.GetMob(GetShielderID());
|
||||||
|
|
||||||
|
if (shielder) {
|
||||||
|
shielder->SetShieldTargetID(0);
|
||||||
|
shielder->SetShielderMitigation(0);
|
||||||
|
shielder->SetShielerMaxDistance(0);
|
||||||
|
shielder->shield_timer.Disable();
|
||||||
|
}
|
||||||
|
SetShielderID(0);
|
||||||
|
SetShieldTargetMitigation(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
//If 'shielder' dies
|
||||||
|
if (GetShieldTargetID()) {
|
||||||
|
|
||||||
|
Mob* shield_target = entity_list.GetMob(GetShieldTargetID());
|
||||||
|
|
||||||
|
if (shield_target) {
|
||||||
|
shield_target->SetShielderID(0);
|
||||||
|
shield_target->SetShieldTargetMitigation(0);
|
||||||
|
}
|
||||||
|
SetShieldTargetID(0);
|
||||||
|
SetShielderMitigation(0);
|
||||||
|
SetShielerMaxDistance(0);
|
||||||
|
shield_timer.Disable();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef BOTS
|
#ifdef BOTS
|
||||||
bool Mob::JoinHealRotationTargetPool(std::shared_ptr<HealRotation>* heal_rotation)
|
bool Mob::JoinHealRotationTargetPool(std::shared_ptr<HealRotation>* heal_rotation)
|
||||||
{
|
{
|
||||||
|
|||||||
+16
-4
@@ -1125,11 +1125,20 @@ public:
|
|||||||
|
|
||||||
Trade* trade;
|
Trade* trade;
|
||||||
|
|
||||||
|
void ShieldAbility(uint32 target_id, int max_shlder_distance = 15, int shield_duration = 12000, int shld_target_mitigation = 50, int shlder_mitigation = 75);
|
||||||
void DoShieldDamageOnShielder(Mob* shield_target, int hit_damage_done, EQ::skills::SkillType skillInUse);
|
void DoShieldDamageOnShielder(Mob* shield_target, int hit_damage_done, EQ::skills::SkillType skillInUse);
|
||||||
inline int GetShielderID() const { return shielder_id; }
|
void ShieldAbilityFinish();
|
||||||
inline void SetShielderID(int ent_id) { shielder_id = ent_id; }
|
void ShieldAbilityClearVariables();
|
||||||
inline int GetShieldTargetID() const { return shield_target_id; }
|
inline uint32 GetShielderID() const { return shielder_id; }
|
||||||
inline void SetShieldTargetID(int ent_id) { shield_target_id = ent_id; }
|
inline void SetShielderID(uint32 val) { shielder_id = val; }
|
||||||
|
inline uint32 GetShieldTargetID() const { return shield_target_id; }
|
||||||
|
inline void SetShieldTargetID(uint32 val) { shield_target_id = val; }
|
||||||
|
inline int GetShieldTargetMitigation() const { return shield_target_mitigation; }
|
||||||
|
inline void SetShieldTargetMitigation(int val) { shield_target_mitigation = val; }
|
||||||
|
inline int GetShielderMitigation() const { return shielder_mitigation; }
|
||||||
|
inline void SetShielderMitigation(int val) { shielder_mitigation = val; }
|
||||||
|
inline int GetMaxShielderDistance() const { return shielder_max_distance; }
|
||||||
|
inline void SetShielerMaxDistance(int val) { shielder_max_distance = val; }
|
||||||
|
|
||||||
inline glm::vec4 GetCurrentWayPoint() const { return m_CurrentWayPoint; }
|
inline glm::vec4 GetCurrentWayPoint() const { return m_CurrentWayPoint; }
|
||||||
inline float GetCWPP() const { return(static_cast<float>(cur_wp_pause)); }
|
inline float GetCWPP() const { return(static_cast<float>(cur_wp_pause)); }
|
||||||
@@ -1433,6 +1442,9 @@ protected:
|
|||||||
Timer shield_timer;
|
Timer shield_timer;
|
||||||
uint32 shield_target_id;
|
uint32 shield_target_id;
|
||||||
uint32 shielder_id;
|
uint32 shielder_id;
|
||||||
|
int shield_target_mitigation;
|
||||||
|
int shielder_mitigation;
|
||||||
|
int shielder_max_distance;
|
||||||
|
|
||||||
//spell casting vars
|
//spell casting vars
|
||||||
Timer spellend_timer;
|
Timer spellend_timer;
|
||||||
|
|||||||
@@ -1128,6 +1128,10 @@ void Mob::AI_Process() {
|
|||||||
if (focus_proc_limit_timer.Check())
|
if (focus_proc_limit_timer.Check())
|
||||||
FocusProcLimitProcess();
|
FocusProcLimitProcess();
|
||||||
|
|
||||||
|
if (shield_timer.Check()) {
|
||||||
|
ShieldAbilityFinish();
|
||||||
|
}
|
||||||
|
|
||||||
auto npcSpawnPoint = CastToNPC()->GetSpawnPoint();
|
auto npcSpawnPoint = CastToNPC()->GetSpawnPoint();
|
||||||
if (GetSpecialAbility(TETHER)) {
|
if (GetSpecialAbility(TETHER)) {
|
||||||
float tether_range = static_cast<float>(GetSpecialAbilityParam(TETHER, 0));
|
float tether_range = static_cast<float>(GetSpecialAbilityParam(TETHER, 0));
|
||||||
|
|||||||
+45
-40
@@ -4179,44 +4179,6 @@ XS(XS_Mob_GetResist) {
|
|||||||
XSRETURN(1);
|
XSRETURN(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
XS(XS_Mob_GetShieldTarget); /* prototype to pass -Wmissing-prototypes */
|
|
||||||
XS(XS_Mob_GetShieldTarget) {
|
|
||||||
dXSARGS;
|
|
||||||
if (items != 1)
|
|
||||||
Perl_croak(aTHX_ "Usage: Mob::GetShieldTarget(THIS)"); // @categories Script Utility
|
|
||||||
{
|
|
||||||
Mob *THIS;
|
|
||||||
Mob *RETVAL;
|
|
||||||
VALIDATE_THIS_IS_MOB;
|
|
||||||
//RETVAL = THIS->GetShieldTarget();
|
|
||||||
ST(0) = sv_newmortal();
|
|
||||||
sv_setref_pv(ST(0), "Mob", (void *) RETVAL);
|
|
||||||
}
|
|
||||||
XSRETURN(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
XS(XS_Mob_SetShieldTarget); /* prototype to pass -Wmissing-prototypes */
|
|
||||||
XS(XS_Mob_SetShieldTarget) {
|
|
||||||
dXSARGS;
|
|
||||||
if (items != 2)
|
|
||||||
Perl_croak(aTHX_ "Usage: Mob::SetShieldTarget(THIS, mob)"); // @categories Script Utility
|
|
||||||
{
|
|
||||||
Mob *THIS;
|
|
||||||
Mob *mob;
|
|
||||||
VALIDATE_THIS_IS_MOB;
|
|
||||||
if (sv_derived_from(ST(1), "Mob")) {
|
|
||||||
IV tmp = SvIV((SV *) SvRV(ST(1)));
|
|
||||||
mob = INT2PTR(Mob *, tmp);
|
|
||||||
} else
|
|
||||||
Perl_croak(aTHX_ "mob is not of type Mob");
|
|
||||||
if (mob == nullptr)
|
|
||||||
Perl_croak(aTHX_ "mob is nullptr, avoiding crash.");
|
|
||||||
|
|
||||||
//THIS->SetShieldTarget(mob);
|
|
||||||
}
|
|
||||||
XSRETURN_EMPTY;
|
|
||||||
}
|
|
||||||
|
|
||||||
XS(XS_Mob_Charmed); /* prototype to pass -Wmissing-prototypes */
|
XS(XS_Mob_Charmed); /* prototype to pass -Wmissing-prototypes */
|
||||||
XS(XS_Mob_Charmed) {
|
XS(XS_Mob_Charmed) {
|
||||||
dXSARGS;
|
dXSARGS;
|
||||||
@@ -6301,6 +6263,50 @@ XS(XS_Mob_AddNimbusEffect) {
|
|||||||
XSRETURN_EMPTY;
|
XSRETURN_EMPTY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
XS(XS_Mob_ShieldAbility); /* prototype to pass -Wmissing-prototypes */
|
||||||
|
XS(XS_Mob_ShieldAbility) {
|
||||||
|
dXSARGS;
|
||||||
|
if (items < 2 || items > 6)
|
||||||
|
Perl_croak(aTHX_ "Usage: Mob::ShieldAbility(THIS, uint32 target_id, int32 max_shielder_distance, int32 shield_duration [ms]"); // @categories Spells and Disciplines
|
||||||
|
{
|
||||||
|
Mob *THIS;
|
||||||
|
uint32 target_id = (uint32)SvUV(ST(1));
|
||||||
|
int32 max_shlder_distance;
|
||||||
|
int32 shld_duration;
|
||||||
|
int32 shld_target_mitigation;
|
||||||
|
int32 shlder_mitigation;
|
||||||
|
|
||||||
|
VALIDATE_THIS_IS_MOB;
|
||||||
|
if (items < 3)
|
||||||
|
max_shlder_distance = 15;
|
||||||
|
else {
|
||||||
|
max_shlder_distance = max_shlder_distance = (int32)SvUV(ST(2));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (items < 4)
|
||||||
|
shld_duration = 12000;
|
||||||
|
else {
|
||||||
|
shld_duration = (int32)SvUV(ST(3));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (items < 5)
|
||||||
|
shld_target_mitigation = 50;
|
||||||
|
else {
|
||||||
|
shld_target_mitigation = (int32)SvUV(ST(4));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (items < 6)
|
||||||
|
shlder_mitigation = 50;
|
||||||
|
else {
|
||||||
|
shlder_mitigation = (int32)SvUV(ST(5));
|
||||||
|
}
|
||||||
|
|
||||||
|
THIS->ShieldAbility(target_id, max_shlder_distance, shld_duration, shld_target_mitigation, shlder_mitigation);
|
||||||
|
|
||||||
|
}
|
||||||
|
XSRETURN_EMPTY;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef BOTS
|
#ifdef BOTS
|
||||||
XS(XS_Mob_CastToBot); /* prototype to pass -Wmissing-prototypes */
|
XS(XS_Mob_CastToBot); /* prototype to pass -Wmissing-prototypes */
|
||||||
XS(XS_Mob_CastToBot)
|
XS(XS_Mob_CastToBot)
|
||||||
@@ -6561,8 +6567,6 @@ XS(boot_Mob) {
|
|||||||
newXSproto(strcpy(buf, "DontRootMeBefore"), XS_Mob_DontRootMeBefore, file, "$");
|
newXSproto(strcpy(buf, "DontRootMeBefore"), XS_Mob_DontRootMeBefore, file, "$");
|
||||||
newXSproto(strcpy(buf, "DontSnareMeBefore"), XS_Mob_DontSnareMeBefore, file, "$");
|
newXSproto(strcpy(buf, "DontSnareMeBefore"), XS_Mob_DontSnareMeBefore, file, "$");
|
||||||
newXSproto(strcpy(buf, "GetResist"), XS_Mob_GetResist, file, "$$");
|
newXSproto(strcpy(buf, "GetResist"), XS_Mob_GetResist, file, "$$");
|
||||||
newXSproto(strcpy(buf, "GetShieldTarget"), XS_Mob_GetShieldTarget, file, "$");
|
|
||||||
newXSproto(strcpy(buf, "SetShieldTarget"), XS_Mob_SetShieldTarget, file, "$$");
|
|
||||||
newXSproto(strcpy(buf, "Charmed"), XS_Mob_Charmed, file, "$");
|
newXSproto(strcpy(buf, "Charmed"), XS_Mob_Charmed, file, "$");
|
||||||
newXSproto(strcpy(buf, "GetLevelHP"), XS_Mob_GetLevelHP, file, "$$");
|
newXSproto(strcpy(buf, "GetLevelHP"), XS_Mob_GetLevelHP, file, "$$");
|
||||||
newXSproto(strcpy(buf, "GetZoneID"), XS_Mob_GetZoneID, file, "$");
|
newXSproto(strcpy(buf, "GetZoneID"), XS_Mob_GetZoneID, file, "$");
|
||||||
@@ -6672,6 +6676,7 @@ XS(boot_Mob) {
|
|||||||
newXSproto(strcpy(buf, "CanRaceEquipItem"), XS_Mob_CanRaceEquipItem, file, "$$");
|
newXSproto(strcpy(buf, "CanRaceEquipItem"), XS_Mob_CanRaceEquipItem, file, "$$");
|
||||||
newXSproto(strcpy(buf, "RemoveAllNimbusEffects"), XS_Mob_RemoveAllNimbusEffects, file, "$");
|
newXSproto(strcpy(buf, "RemoveAllNimbusEffects"), XS_Mob_RemoveAllNimbusEffects, file, "$");
|
||||||
newXSproto(strcpy(buf, "AddNimbusEffect"), XS_Mob_AddNimbusEffect, file, "$$");
|
newXSproto(strcpy(buf, "AddNimbusEffect"), XS_Mob_AddNimbusEffect, file, "$$");
|
||||||
|
newXSproto(strcpy(buf, "ShieldAbility"), XS_Mob_ShieldAbility, file, "$$$$$$");
|
||||||
#ifdef BOTS
|
#ifdef BOTS
|
||||||
newXSproto(strcpy(buf, "CastToBot"), XS_Mob_CastToBot, file, "$");
|
newXSproto(strcpy(buf, "CastToBot"), XS_Mob_CastToBot, file, "$");
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -2950,6 +2950,20 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case SE_PetShield: {
|
||||||
|
if (IsPet()) {
|
||||||
|
Mob* petowner = GetOwner();
|
||||||
|
if (petowner) {
|
||||||
|
|
||||||
|
int shield_duration = spells[spell_id].base[i] * 12 * 1000;
|
||||||
|
int shld_target_mitigation = spells[spell_id].base2[i] ? spells[spell_id].base2[i] : 50;
|
||||||
|
int shlder_mitigation = spells[spell_id].max[i] ? spells[spell_id].base2[i] : 50;
|
||||||
|
ShieldAbility(petowner->GetID(), 25, shield_duration, shld_target_mitigation, shlder_mitigation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case SE_PersistentEffect:
|
case SE_PersistentEffect:
|
||||||
MakeAura(spell_id);
|
MakeAura(spell_id);
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -287,7 +287,9 @@
|
|||||||
#define SUSPEND_MINION_SUSPEND 3268 //%1 tells you, 'By your command, master.'
|
#define SUSPEND_MINION_SUSPEND 3268 //%1 tells you, 'By your command, master.'
|
||||||
#define ONLY_SUMMONED_PETS 3269 //3269 This effect only works with summoned pets.
|
#define ONLY_SUMMONED_PETS 3269 //3269 This effect only works with summoned pets.
|
||||||
#define SUSPEND_MINION_FIGHTING 3270 //Your pet must be at peace, first.
|
#define SUSPEND_MINION_FIGHTING 3270 //Your pet must be at peace, first.
|
||||||
|
#define SHIELD_TARGET_NPC 3278 //You must first target a living Player Character.
|
||||||
#define ALREADY_SHIELDED 3279 //Either you or your target is already being shielded.
|
#define ALREADY_SHIELDED 3279 //Either you or your target is already being shielded.
|
||||||
|
#define ALREADY_SHIELDING 3280 //Either you or your target is already shielding another.
|
||||||
#define START_SHIELDING 3281 //%1 begins to use %2 as a living shield!
|
#define START_SHIELDING 3281 //%1 begins to use %2 as a living shield!
|
||||||
#define END_SHIELDING 3282 //%1 ceases protecting %2.
|
#define END_SHIELDING 3282 //%1 ceases protecting %2.
|
||||||
#define TRADESKILL_MISSING_ITEM 3455 //You are missing a %1.
|
#define TRADESKILL_MISSING_ITEM 3455 //You are missing a %1.
|
||||||
|
|||||||
Reference in New Issue
Block a user