mirror of
https://github.com/EQEmu/Server.git
synced 2026-06-24 13:38:21 +00:00
shield ability initial work
This commit is contained in:
+2
-2
@@ -592,7 +592,7 @@ typedef enum {
|
|||||||
#define SE_ReduceSkillTimer 227 // implemented
|
#define SE_ReduceSkillTimer 227 // implemented
|
||||||
#define SE_ReduceFallDamage 228 // implented - reduce the damage that you take from falling
|
#define SE_ReduceFallDamage 228 // implented - reduce the damage that you take from falling
|
||||||
#define SE_PersistantCasting 229 // implemented
|
#define SE_PersistantCasting 229 // implemented
|
||||||
#define SE_ExtendedShielding 230 // not used as bonus - increase range of /shield ability
|
#define SE_ExtendedShielding 230 // implemented XXXXXXXXX not used as bonus - increase range of /shield ability
|
||||||
#define SE_StunBashChance 231 // implemented - increase chance to stun from bash.
|
#define SE_StunBashChance 231 // implemented - increase chance to stun from bash.
|
||||||
#define SE_DivineSave 232 // implemented (base1 == % chance on death to insta-res) (base2 == spell cast on save)
|
#define SE_DivineSave 232 // implemented (base1 == % chance on death to insta-res) (base2 == spell cast on save)
|
||||||
#define SE_Metabolism 233 // implemented - Modifies food/drink consumption rates.
|
#define SE_Metabolism 233 // implemented - Modifies food/drink consumption rates.
|
||||||
@@ -617,7 +617,7 @@ typedef enum {
|
|||||||
#define SE_FrontalBackstabChance 252 // implemented[AA] - chance to perform a full damage backstab from front.
|
#define SE_FrontalBackstabChance 252 // implemented[AA] - chance to perform a full damage backstab from front.
|
||||||
#define SE_FrontalBackstabMinDmg 253 // implemented[AA] - allow a frontal backstab for mininum damage.
|
#define SE_FrontalBackstabMinDmg 253 // implemented[AA] - allow a frontal backstab for mininum damage.
|
||||||
#define SE_Blank 254 // implemented
|
#define SE_Blank 254 // implemented
|
||||||
#define SE_ShieldDuration 255 // not implemented as bonus - increases duration of /shield
|
#define SE_ShieldDuration 255 // implemented, XXXXXXXXXXXX not implemented as bonus - increases duration of /shield
|
||||||
#define SE_ShroudofStealth 256 // implemented
|
#define SE_ShroudofStealth 256 // implemented
|
||||||
#define SE_PetDiscipline 257 // not implemented as bonus - /pet hold - official name is GivePetHold
|
#define SE_PetDiscipline 257 // not implemented as bonus - /pet hold - official name is GivePetHold
|
||||||
#define SE_TripleBackstab 258 // implemented[AA] - chance to perform a triple backstab
|
#define SE_TripleBackstab 258 // implemented[AA] - chance to perform a triple backstab
|
||||||
|
|||||||
@@ -5278,9 +5278,49 @@ 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));
|
||||||
|
|
||||||
|
if (defender->shield_ability.shielder_id = GetID()) {
|
||||||
|
hit.damage_done *= 0.50;//Don't round.
|
||||||
|
DoShieldDamageOnShielder(defender, hit);
|
||||||
|
}
|
||||||
|
|
||||||
CheckNumHitsRemaining(NumHit::OutgoingHitSuccess);
|
CheckNumHitsRemaining(NumHit::OutgoingHitSuccess);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Mob::DoShieldDamageOnShielder(Mob* defender, DamageHitInfo &hit)
|
||||||
|
{
|
||||||
|
if (!defender) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Mob *current_shielder = entity_list.GetMob(defender->shield_ability.shielder_id);
|
||||||
|
|
||||||
|
if (!current_shielder) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int mitigation = 75;
|
||||||
|
|
||||||
|
if (current_shielder->HasShieldEquiped() && current_shielder->IsClient()) {
|
||||||
|
|
||||||
|
EQ::ItemInstance* inst = CastToClient()->GetInv().GetItem(EQ::invslot::slotSecondary);
|
||||||
|
|
||||||
|
if (inst) {
|
||||||
|
|
||||||
|
const EQ::ItemData* shield = inst->GetItem();
|
||||||
|
if (shield && shield->ItemType == EQ::item::ItemTypeShield) {
|
||||||
|
mitigation -= shield->AC * 0.50; //1% increase per 2 AC
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mitigation = std::max(mitigation, 50);
|
||||||
|
|
||||||
|
int shielder_damage_taken = hit.damage_done * 75 / 100;
|
||||||
|
|
||||||
|
current_shielder->Damage(this, shielder_damage_taken, SPELL_UNKNOWN, hit.skill, true, -1, false, m_specialattacks);
|
||||||
|
current_shielder->CheckNumHitsRemaining(NumHit::OutgoingHitSuccess);
|
||||||
|
}
|
||||||
|
|
||||||
void Mob::CommonBreakInvisibleFromCombat()
|
void Mob::CommonBreakInvisibleFromCombat()
|
||||||
{
|
{
|
||||||
//break invis when you attack
|
//break invis when you attack
|
||||||
|
|||||||
+32
-4
@@ -1583,6 +1583,22 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case SE_ExtendedShielding:
|
||||||
|
{
|
||||||
|
if (newbon->ExtendedShielding < base1) {
|
||||||
|
newbon->ExtendedShielding = base1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case SE_ShieldDuration:
|
||||||
|
{
|
||||||
|
if (newbon->ShieldDuration < base1) {
|
||||||
|
newbon->ShieldDuration = base1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
// to do
|
// to do
|
||||||
case SE_PetDiscipline:
|
case SE_PetDiscipline:
|
||||||
break;
|
break;
|
||||||
@@ -1592,10 +1608,6 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon)
|
|||||||
break;
|
break;
|
||||||
case SE_SecondaryForte:
|
case SE_SecondaryForte:
|
||||||
break;
|
break;
|
||||||
case SE_ExtendedShielding:
|
|
||||||
break;
|
|
||||||
case SE_ShieldDuration:
|
|
||||||
break;
|
|
||||||
case SE_ReduceApplyPoisonTime:
|
case SE_ReduceApplyPoisonTime:
|
||||||
break;
|
break;
|
||||||
case SE_NimbleEvasion:
|
case SE_NimbleEvasion:
|
||||||
@@ -3474,6 +3486,22 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne
|
|||||||
new_bonus->Pet_Add_Atk += effect_value;
|
new_bonus->Pet_Add_Atk += effect_value;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case SE_ExtendedShielding:
|
||||||
|
{
|
||||||
|
if (new_bonus->ExtendedShielding < effect_value) {
|
||||||
|
new_bonus->ExtendedShielding = effect_value;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case SE_ShieldDuration:
|
||||||
|
{
|
||||||
|
if (new_bonus->ShieldDuration < effect_value) {
|
||||||
|
new_bonus->ShieldDuration = effect_value;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
//Special custom cases for loading effects on to NPC from 'npc_spels_effects' table
|
//Special custom cases for loading effects on to NPC from 'npc_spels_effects' table
|
||||||
if (IsAISpellEffect) {
|
if (IsAISpellEffect) {
|
||||||
|
|
||||||
|
|||||||
+47
-65
@@ -12808,83 +12808,65 @@ void Client::Handle_OP_Shielding(const EQApplicationPacket *app)
|
|||||||
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;
|
||||||
}
|
}
|
||||||
if (GetClass() != WARRIOR)
|
//Enforce level
|
||||||
{
|
//Augs on shieldd?
|
||||||
|
|
||||||
|
if (GetLevel() < 30) {
|
||||||
|
return; //Client gives message
|
||||||
|
}
|
||||||
|
|
||||||
|
if (GetClass() != WARRIOR){
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (shield_target)
|
|
||||||
{
|
|
||||||
entity_list.MessageCloseString(
|
|
||||||
this, false, 100, 0,
|
|
||||||
END_SHIELDING, GetName(), shield_target->GetName());
|
|
||||||
for (int y = 0; y < 2; y++)
|
|
||||||
{
|
|
||||||
if (shield_target->shielder[y].shielder_id == GetID())
|
|
||||||
{
|
|
||||||
shield_target->shielder[y].shielder_id = 0;
|
|
||||||
shield_target->shielder[y].shielder_bonus = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Shielding_Struct* shield = (Shielding_Struct*)app->pBuffer;
|
Shielding_Struct* shield = (Shielding_Struct*)app->pBuffer;
|
||||||
|
|
||||||
shield_target = entity_list.GetMob(shield->target_id);
|
shield_target = entity_list.GetMob(shield->target_id);
|
||||||
bool ack = false;
|
|
||||||
EQ::ItemInstance* inst = GetInv().GetItem(EQ::invslot::slotSecondary);
|
if (!shield_target) {
|
||||||
if (!shield_target)
|
|
||||||
return;
|
|
||||||
if (inst)
|
|
||||||
{
|
|
||||||
const EQ::ItemData* shield = inst->GetItem();
|
|
||||||
if (shield && shield->ItemType == EQ::item::ItemTypeShield)
|
|
||||||
{
|
|
||||||
for (int x = 0; x < 2; x++)
|
|
||||||
{
|
|
||||||
if (shield_target->shielder[x].shielder_id == 0)
|
|
||||||
{
|
|
||||||
entity_list.MessageCloseString(
|
|
||||||
this, false, 100, 0,
|
|
||||||
START_SHIELDING, GetName(), shield_target->GetName());
|
|
||||||
shield_target->shielder[x].shielder_id = GetID();
|
|
||||||
int shieldbonus = shield->AC * 2;
|
|
||||||
switch (GetAA(197))
|
|
||||||
{
|
|
||||||
case 1:
|
|
||||||
shieldbonus = shieldbonus * 115 / 100;
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
shieldbonus = shieldbonus * 125 / 100;
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
shieldbonus = shieldbonus * 150 / 100;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
shield_target->shielder[x].shielder_bonus = shieldbonus;
|
|
||||||
shield_timer.Start();
|
|
||||||
ack = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Message(0, "You must have a shield equipped to shield a target!");
|
|
||||||
shield_target = 0;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
if (shield_target->IsNPC()) {
|
||||||
Message(0, "You must have a shield equipped to shield a target!");
|
//You must first target a living player //TODO Find string
|
||||||
shield_target = 0;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!ack)
|
|
||||||
{
|
if (shield_target->GetID() == GetID()) { //Client will give message "You can not shield yourself"
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Does 'Shield Target' already have a 'Shielder'
|
||||||
|
if (shield_target->shield_ability.shielder_id = GetID()) {
|
||||||
MessageString(Chat::White, ALREADY_SHIELDED);
|
MessageString(Chat::White, ALREADY_SHIELDED);
|
||||||
shield_target = 0;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Does 'Shielder' already have a 'Shield Target' already have a shielder
|
||||||
|
if (shield_ability.shielder_id = GetID()) {
|
||||||
|
MessageString(Chat::White, ALREADY_SHIELDED);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
//AA to increase SPA 230 extended shielding
|
||||||
|
if (shield_target->CalculateDistance(GetX(), GetY(), GetZ()) > 15.0f) {
|
||||||
|
return; //Too far away, no message is given thoughh. //TODO: Timer to enforce distance check
|
||||||
|
}
|
||||||
|
|
||||||
|
entity_list.MessageCloseString(this, false, 100, 0, START_SHIELDING, GetName(), shield_target->GetName());
|
||||||
|
|
||||||
|
//Apply to Shielder
|
||||||
|
shield_ability.shielder_id = GetID();
|
||||||
|
shield_ability.shield_target_id = shield_target->GetID();
|
||||||
|
|
||||||
|
//Apply to Shield Target
|
||||||
|
shield_target->shield_ability.shielder_id = GetID();
|
||||||
|
shield_target->shield_ability.shield_target_id = shield_target->GetID();
|
||||||
|
|
||||||
|
//Calculate AA for adding time SPA 255 extend shield duration
|
||||||
|
|
||||||
|
shield_timer.Start(12000);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -548,6 +548,8 @@ struct StatBonuses {
|
|||||||
|
|
||||||
|
|
||||||
// AAs
|
// AAs
|
||||||
|
int32 ShieldDuration; // extends duration of /shield ability
|
||||||
|
int32 ExtendedShielding; // extends range of /shield ability
|
||||||
int8 Packrat; // weight reduction for items, 1 point = 10%
|
int8 Packrat; // weight reduction for items, 1 point = 10%
|
||||||
uint8 BuffSlotIncrease; // Increases number of available buff slots
|
uint8 BuffSlotIncrease; // Increases number of available buff slots
|
||||||
uint32 DelayDeath; // how far below 0 hp you can go
|
uint32 DelayDeath; // how far below 0 hp you can go
|
||||||
@@ -678,10 +680,17 @@ typedef struct
|
|||||||
} tProc;
|
} tProc;
|
||||||
|
|
||||||
struct Shielders_Struct {
|
struct Shielders_Struct {
|
||||||
|
|
||||||
uint32 shielder_id;
|
uint32 shielder_id;
|
||||||
uint16 shielder_bonus;
|
uint16 shielder_bonus;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct ShieldAbility_Struct{
|
||||||
|
|
||||||
|
uint32 shield_target_id;
|
||||||
|
uint32 shielder_id;
|
||||||
|
};
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
uint16 increment;
|
uint16 increment;
|
||||||
|
|||||||
@@ -381,6 +381,9 @@ Mob::Mob(
|
|||||||
shielder[m].shielder_bonus = 0;
|
shielder[m].shielder_bonus = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
shield_ability.shield_target_id = 0;
|
||||||
|
shield_ability.shielder_id = 0;
|
||||||
|
|
||||||
destructibleobject = false;
|
destructibleobject = false;
|
||||||
wandertype = 0;
|
wandertype = 0;
|
||||||
pausetype = 0;
|
pausetype = 0;
|
||||||
|
|||||||
@@ -1126,8 +1126,16 @@ public:
|
|||||||
void SetMoved(bool moveflag) { moved = moveflag; }
|
void SetMoved(bool moveflag) { moved = moveflag; }
|
||||||
|
|
||||||
Shielders_Struct shielder[MAX_SHIELDERS];
|
Shielders_Struct shielder[MAX_SHIELDERS];
|
||||||
|
|
||||||
Trade* trade;
|
Trade* trade;
|
||||||
|
|
||||||
|
ShieldAbility_Struct shield_ability;
|
||||||
|
void DoShieldDamageOnShielder(Mob* defender, DamageHitInfo &hit);
|
||||||
|
inline int GetShielderID() { return shield_ability.shielder_id; }
|
||||||
|
inline int SetShielderID(int ent_id) { shield_ability.shielder_id = ent_id; }
|
||||||
|
inline int GetShieldTargetID() { return shield_ability.shield_target_id; }
|
||||||
|
inline int SetShieldTargetID(int ent_id) { shield_ability.shield_target_id = ent_id; }
|
||||||
|
|
||||||
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)); }
|
||||||
inline int GetCWP() const { return(cur_wp); }
|
inline int GetCWP() const { return(cur_wp); }
|
||||||
|
|||||||
Reference in New Issue
Block a user