mirror of
https://github.com/EQEmu/Server.git
synced 2025-12-12 17:51:28 +00:00
Implement mob and client melee push
New rules: Combat:MeleePush turns melee push on/off Combat:MeleePushChance is the chance that an NPC will be pushed Clients are pushed every successful hit, need to verify or disprove this
This commit is contained in:
parent
8b4d601027
commit
06f4fd49ef
@ -1,5 +1,10 @@
|
|||||||
EQEMu Changelog (Started on Sept 24, 2003 15:50)
|
EQEMu Changelog (Started on Sept 24, 2003 15:50)
|
||||||
-------------------------------------------------------
|
-------------------------------------------------------
|
||||||
|
== 04/30/2015 ==
|
||||||
|
demonstar55: Implement mob and client melee push
|
||||||
|
You can set Combat:MeleePush to false to turn off or change Combat:MeleePushChance to increase the chance an NPC can be pushed
|
||||||
|
PCs are always pushed, need to do more testing to verify.
|
||||||
|
|
||||||
== 04/22/2015 ==
|
== 04/22/2015 ==
|
||||||
Uleat: Probable fix for 'Debug Assertion Failure' in Client::GarbleMessage() when calling the 'isalpha' macro.
|
Uleat: Probable fix for 'Debug Assertion Failure' in Client::GarbleMessage() when calling the 'isalpha' macro.
|
||||||
ref: https://connect.microsoft.com/VisualStudio/feedback/details/932876/calling-isdigit-with-a-signed-char-1-results-in-a-assert-failure-in-debug-compiles
|
ref: https://connect.microsoft.com/VisualStudio/feedback/details/932876/calling-isdigit-with-a-signed-char-1-results-in-a-assert-failure-in-debug-compiles
|
||||||
|
|||||||
@ -1318,9 +1318,9 @@ struct CombatDamage_Struct
|
|||||||
/* 04 */ uint8 type; //slashing, etc. 231 (0xE7) for spells
|
/* 04 */ uint8 type; //slashing, etc. 231 (0xE7) for spells
|
||||||
/* 05 */ uint16 spellid;
|
/* 05 */ uint16 spellid;
|
||||||
/* 07 */ uint32 damage;
|
/* 07 */ uint32 damage;
|
||||||
/* 11 */ uint32 unknown11;
|
/* 11 */ float force;
|
||||||
/* 15 */ uint32 sequence; // see above notes in Action_Struct
|
/* 15 */ float meleepush_xy; // see above notes in Action_Struct
|
||||||
/* 19 */ uint32 unknown19;
|
/* 19 */ float meleepush_z;
|
||||||
/* 23 */
|
/* 23 */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -658,7 +658,9 @@ namespace RoF
|
|||||||
OUT(type);
|
OUT(type);
|
||||||
OUT(spellid);
|
OUT(spellid);
|
||||||
OUT(damage);
|
OUT(damage);
|
||||||
eq->sequence = emu->sequence;
|
OUT(force)
|
||||||
|
OUT(meleepush_xy);
|
||||||
|
OUT(meleepush_z)
|
||||||
|
|
||||||
FINISH_ENCODE();
|
FINISH_ENCODE();
|
||||||
}
|
}
|
||||||
@ -4389,7 +4391,7 @@ namespace RoF
|
|||||||
IN(type);
|
IN(type);
|
||||||
IN(spellid);
|
IN(spellid);
|
||||||
IN(damage);
|
IN(damage);
|
||||||
emu->sequence = eq->sequence;
|
IN(meleepush_xy);
|
||||||
|
|
||||||
FINISH_DIRECT_DECODE();
|
FINISH_DIRECT_DECODE();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -729,7 +729,9 @@ namespace RoF2
|
|||||||
OUT(type);
|
OUT(type);
|
||||||
OUT(spellid);
|
OUT(spellid);
|
||||||
OUT(damage);
|
OUT(damage);
|
||||||
eq->sequence = emu->sequence;
|
OUT(force)
|
||||||
|
OUT(meleepush_xy);
|
||||||
|
OUT(meleepush_z)
|
||||||
|
|
||||||
FINISH_ENCODE();
|
FINISH_ENCODE();
|
||||||
}
|
}
|
||||||
@ -4538,7 +4540,7 @@ namespace RoF2
|
|||||||
IN(type);
|
IN(type);
|
||||||
IN(spellid);
|
IN(spellid);
|
||||||
IN(damage);
|
IN(damage);
|
||||||
emu->sequence = eq->sequence;
|
IN(meleepush_xy);
|
||||||
|
|
||||||
FINISH_DIRECT_DECODE();
|
FINISH_DIRECT_DECODE();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1484,9 +1484,10 @@ struct CombatDamage_Struct
|
|||||||
/* 04 */ uint8 type; //slashing, etc. 231 (0xE7) for spells
|
/* 04 */ uint8 type; //slashing, etc. 231 (0xE7) for spells
|
||||||
/* 05 */ uint32 spellid;
|
/* 05 */ uint32 spellid;
|
||||||
/* 09 */ int32 damage;
|
/* 09 */ int32 damage;
|
||||||
/* 13 */ float unknown11; // cd cc cc 3d
|
/* 13 */ float force; // cd cc cc 3d
|
||||||
/* 17 */ float sequence; // see above notes in Action_Struct
|
/* 17 */ float meleepush_xy; // see above notes in Action_Struct
|
||||||
/* 21 */ uint8 unknown19[9]; // was [9]
|
/* 21 */ float meleepush_z;
|
||||||
|
/* 25 */ uint8 unknown25[5]; // was [9]
|
||||||
/* 30 */
|
/* 30 */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -1514,9 +1514,10 @@ struct CombatDamage_Struct
|
|||||||
/* 04 */ uint8 type; //slashing, etc. 231 (0xE7) for spells
|
/* 04 */ uint8 type; //slashing, etc. 231 (0xE7) for spells
|
||||||
/* 05 */ uint32 spellid;
|
/* 05 */ uint32 spellid;
|
||||||
/* 09 */ int32 damage;
|
/* 09 */ int32 damage;
|
||||||
/* 13 */ float unknown11; // cd cc cc 3d
|
/* 13 */ float force; // cd cc cc 3d
|
||||||
/* 17 */ float sequence; // see above notes in Action_Struct
|
/* 17 */ float meleepush_xy; // see above notes in Action_Struct
|
||||||
/* 21 */ uint8 unknown19[9]; // was [9]
|
/* 21 */ float meleepush_z;
|
||||||
|
/* 25 */ uint8 unknown25[5]; // was [9]
|
||||||
/* 30 */
|
/* 30 */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -446,7 +446,9 @@ namespace SoD
|
|||||||
OUT(type);
|
OUT(type);
|
||||||
OUT(spellid);
|
OUT(spellid);
|
||||||
OUT(damage);
|
OUT(damage);
|
||||||
eq->sequence = emu->sequence;
|
OUT(force)
|
||||||
|
OUT(meleepush_xy);
|
||||||
|
OUT(meleepush_z)
|
||||||
|
|
||||||
FINISH_ENCODE();
|
FINISH_ENCODE();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1272,9 +1272,10 @@ struct CombatDamage_Struct
|
|||||||
/* 04 */ uint8 type; //slashing, etc. 231 (0xE7) for spells
|
/* 04 */ uint8 type; //slashing, etc. 231 (0xE7) for spells
|
||||||
/* 05 */ uint16 spellid;
|
/* 05 */ uint16 spellid;
|
||||||
/* 07 */ int32 damage;
|
/* 07 */ int32 damage;
|
||||||
/* 11 */ float unknown11; // cd cc cc 3d
|
/* 11 */ float force; // cd cc cc 3d
|
||||||
/* 15 */ float sequence; // see above notes in Action_Struct
|
/* 15 */ float meleepush_xy; // see above notes in Action_Struct
|
||||||
/* 19 */ uint8 unknown19[9]; // was [9]
|
/* 19 */ float meleepush_z;
|
||||||
|
/* 23 */ uint8 unknown23[5]; // was [9]
|
||||||
/* 28 */
|
/* 28 */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -426,7 +426,9 @@ namespace SoF
|
|||||||
OUT(type);
|
OUT(type);
|
||||||
OUT(spellid);
|
OUT(spellid);
|
||||||
OUT(damage);
|
OUT(damage);
|
||||||
eq->sequence = emu->sequence;
|
OUT(force)
|
||||||
|
OUT(meleepush_xy);
|
||||||
|
OUT(meleepush_z)
|
||||||
|
|
||||||
FINISH_ENCODE();
|
FINISH_ENCODE();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1249,9 +1249,10 @@ struct CombatDamage_Struct
|
|||||||
/* 04 */ uint8 type; //slashing, etc. 231 (0xE7) for spells
|
/* 04 */ uint8 type; //slashing, etc. 231 (0xE7) for spells
|
||||||
/* 05 */ uint16 spellid;
|
/* 05 */ uint16 spellid;
|
||||||
/* 07 */ int32 damage;
|
/* 07 */ int32 damage;
|
||||||
/* 11 */ float unknown11; // cd cc cc 3d
|
/* 11 */ float force; // cd cc cc 3d
|
||||||
/* 15 */ float sequence; // see above notes in Action_Struct
|
/* 15 */ float meleepush_xy; // see above notes in Action_Struct
|
||||||
/* 19 */ uint8 unknown19[9]; // was [9]
|
/* 19 */ float meleepush_z;
|
||||||
|
/* 23 */ uint8 unknown23[5]; // was [9]
|
||||||
/* 28 */
|
/* 28 */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -1101,9 +1101,9 @@ struct CombatDamage_Struct
|
|||||||
/* 04 */ uint8 type; //slashing, etc. 231 (0xE7) for spells
|
/* 04 */ uint8 type; //slashing, etc. 231 (0xE7) for spells
|
||||||
/* 05 */ uint16 spellid;
|
/* 05 */ uint16 spellid;
|
||||||
/* 07 */ uint32 damage;
|
/* 07 */ uint32 damage;
|
||||||
/* 11 */ uint32 unknown11;
|
/* 11 */ float force;
|
||||||
/* 15 */ uint32 sequence; // see above notes in Action_Struct
|
/* 15 */ float meleepush_xy; // see above notes in Action_Struct
|
||||||
/* 19 */ uint32 unknown19;
|
/* 19 */ float meleepush_z;
|
||||||
/* 23 */
|
/* 23 */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -581,7 +581,9 @@ namespace UF
|
|||||||
OUT(type);
|
OUT(type);
|
||||||
OUT(spellid);
|
OUT(spellid);
|
||||||
OUT(damage);
|
OUT(damage);
|
||||||
eq->sequence = emu->sequence;
|
OUT(force)
|
||||||
|
OUT(meleepush_xy);
|
||||||
|
OUT(meleepush_z)
|
||||||
|
|
||||||
FINISH_ENCODE();
|
FINISH_ENCODE();
|
||||||
}
|
}
|
||||||
@ -3356,7 +3358,7 @@ namespace UF
|
|||||||
IN(type);
|
IN(type);
|
||||||
IN(spellid);
|
IN(spellid);
|
||||||
IN(damage);
|
IN(damage);
|
||||||
emu->sequence = eq->sequence;
|
IN(meleepush_xy);
|
||||||
|
|
||||||
FINISH_DIRECT_DECODE();
|
FINISH_DIRECT_DECODE();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1330,9 +1330,10 @@ struct CombatDamage_Struct
|
|||||||
/* 04 */ uint8 type; //slashing, etc. 231 (0xE7) for spells
|
/* 04 */ uint8 type; //slashing, etc. 231 (0xE7) for spells
|
||||||
/* 05 */ uint16 spellid;
|
/* 05 */ uint16 spellid;
|
||||||
/* 07 */ int32 damage;
|
/* 07 */ int32 damage;
|
||||||
/* 11 */ float unknown11; // cd cc cc 3d
|
/* 11 */ float force; // cd cc cc 3d
|
||||||
/* 15 */ float sequence; // see above notes in Action_Struct
|
/* 15 */ float meleepush_xy; // see above notes in Action_Struct
|
||||||
/* 19 */ uint8 unknown19[9]; // was [9]
|
/* 19 */ float meleepush_z;
|
||||||
|
/* 23 */ uint8 unknown23[5]; // was [9]
|
||||||
/* 28 */
|
/* 28 */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -438,6 +438,8 @@ RULE_INT ( Combat, BerserkerFrenzyStart, 35)
|
|||||||
RULE_INT ( Combat, BerserkerFrenzyEnd, 45)
|
RULE_INT ( Combat, BerserkerFrenzyEnd, 45)
|
||||||
RULE_BOOL ( Combat, OneProcPerWeapon, true) //If enabled, One proc per weapon per round
|
RULE_BOOL ( Combat, OneProcPerWeapon, true) //If enabled, One proc per weapon per round
|
||||||
RULE_BOOL ( Combat, ProjectileDmgOnImpact, true) //If enabled, projectiles (ie arrows) will hit on impact, instead of instantly.
|
RULE_BOOL ( Combat, ProjectileDmgOnImpact, true) //If enabled, projectiles (ie arrows) will hit on impact, instead of instantly.
|
||||||
|
RULE_BOOL ( Combat, MeleePush, true) // enable melee push
|
||||||
|
RULE_INT ( Combat, MeleePushChance, 50) // (NPCs) chance the target will be pushed. Made up, 100 actually isn't that bad
|
||||||
RULE_CATEGORY_END()
|
RULE_CATEGORY_END()
|
||||||
|
|
||||||
RULE_CATEGORY( NPC )
|
RULE_CATEGORY( NPC )
|
||||||
|
|||||||
@ -55,3 +55,40 @@ bool EQEmu::IsSpecializedSkill(SkillUseTypes skill)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float EQEmu::GetSkillMeleePushForce(SkillUseTypes skill)
|
||||||
|
{
|
||||||
|
// This is the force/magnitude of the push from an attack of this skill type
|
||||||
|
// You can find these numbers in the clients skill struct
|
||||||
|
switch (skill) {
|
||||||
|
case Skill1HBlunt:
|
||||||
|
case Skill1HSlashing:
|
||||||
|
case SkillHandtoHand:
|
||||||
|
case SkillThrowing:
|
||||||
|
return 0.1f;
|
||||||
|
case Skill2HBlunt:
|
||||||
|
case Skill2HSlashing:
|
||||||
|
case SkillEagleStrike:
|
||||||
|
case SkillKick:
|
||||||
|
case SkillTigerClaw:
|
||||||
|
//case Skill2HPiercing:
|
||||||
|
return 0.2f;
|
||||||
|
case SkillArchery:
|
||||||
|
return 0.15f;
|
||||||
|
case SkillBackstab:
|
||||||
|
case SkillBash:
|
||||||
|
return 0.3f;
|
||||||
|
case SkillDragonPunch:
|
||||||
|
case SkillRoundKick:
|
||||||
|
return 0.25f;
|
||||||
|
case SkillFlyingKick:
|
||||||
|
return 0.4f;
|
||||||
|
case Skill1HPiercing:
|
||||||
|
case SkillFrenzy:
|
||||||
|
return 0.05f;
|
||||||
|
case SkillIntimidation:
|
||||||
|
return 2.5f;
|
||||||
|
default:
|
||||||
|
return 0.0f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -270,6 +270,7 @@ typedef enum {
|
|||||||
namespace EQEmu {
|
namespace EQEmu {
|
||||||
bool IsTradeskill(SkillUseTypes skill);
|
bool IsTradeskill(SkillUseTypes skill);
|
||||||
bool IsSpecializedSkill(SkillUseTypes skill);
|
bool IsSpecializedSkill(SkillUseTypes skill);
|
||||||
|
float GetSkillMeleePushForce(SkillUseTypes skill);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
2
utils/sql/git/optional/2015_4_30_MeleePush.sql
Normal file
2
utils/sql/git/optional/2015_4_30_MeleePush.sql
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
INSERT INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (1, 'Combat:MeleePush', 'true', 'Turns on Melee Push.');
|
||||||
|
INSERT INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (1, 'Combat:MeleePushChance', '50', 'Chance that an NPC can be pushed from melee.');
|
||||||
@ -3708,6 +3708,23 @@ void Mob::CommonDamage(Mob* attacker, int32 &damage, const uint16 spell_id, cons
|
|||||||
a->type = SkillDamageTypes[skill_used]; // was 0x1c
|
a->type = SkillDamageTypes[skill_used]; // was 0x1c
|
||||||
a->damage = damage;
|
a->damage = damage;
|
||||||
a->spellid = spell_id;
|
a->spellid = spell_id;
|
||||||
|
a->meleepush_xy = attacker->GetHeading() * 2.0f;
|
||||||
|
if (RuleB(Combat, MeleePush) && damage > 0 && !IsRooted() &&
|
||||||
|
(IsClient() || zone->random.Roll(RuleI(Combat, MeleePushChance)))) {
|
||||||
|
a->force = EQEmu::GetSkillMeleePushForce(skill_used);
|
||||||
|
// update NPC stuff
|
||||||
|
auto new_pos = glm::vec3(m_Position.x + (a->force * std::sin(a->meleepush_xy) + m_Delta.x),
|
||||||
|
m_Position.y + (a->force * std::cos(a->meleepush_xy) + m_Delta.y), m_Position.z);
|
||||||
|
if (zone->zonemap->CheckLoS(glm::vec3(m_Position), new_pos)) { // If we have LoS on the new loc it should be reachable.
|
||||||
|
if (IsNPC()) {
|
||||||
|
// Is this adequate?
|
||||||
|
Teleport(new_pos);
|
||||||
|
SendPosUpdate();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
a->force = 0.0f; // we couldn't move there, so lets not
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//Note: if players can become pets, they will not receive damage messages of their own
|
//Note: if players can become pets, they will not receive damage messages of their own
|
||||||
//this was done to simplify the code here (since we can only effectively skip one mob on queue)
|
//this was done to simplify the code here (since we can only effectively skip one mob on queue)
|
||||||
|
|||||||
@ -921,7 +921,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial)
|
|||||||
cd->source = action->source;
|
cd->source = action->source;
|
||||||
cd->type = action->type;
|
cd->type = action->type;
|
||||||
cd->spellid = action->spell;
|
cd->spellid = action->spell;
|
||||||
cd->sequence = action->sequence;
|
cd->meleepush_xy = action->sequence;
|
||||||
|
|
||||||
CastToClient()->QueuePacket(action_packet);
|
CastToClient()->QueuePacket(action_packet);
|
||||||
if(caster->IsClient() && caster != this)
|
if(caster->IsClient() && caster != this)
|
||||||
@ -970,7 +970,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial)
|
|||||||
cd->source = action->source;
|
cd->source = action->source;
|
||||||
cd->type = action->type;
|
cd->type = action->type;
|
||||||
cd->spellid = action->spell;
|
cd->spellid = action->spell;
|
||||||
cd->sequence = action->sequence;
|
cd->meleepush_xy = action->sequence;
|
||||||
|
|
||||||
CastToClient()->QueuePacket(action_packet);
|
CastToClient()->QueuePacket(action_packet);
|
||||||
if(caster->IsClient() && caster != this)
|
if(caster->IsClient() && caster != this)
|
||||||
@ -1006,7 +1006,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial)
|
|||||||
cd->source = action->source;
|
cd->source = action->source;
|
||||||
cd->type = action->type;
|
cd->type = action->type;
|
||||||
cd->spellid = action->spell;
|
cd->spellid = action->spell;
|
||||||
cd->sequence = action->sequence;
|
cd->meleepush_xy = action->sequence;
|
||||||
|
|
||||||
CastToClient()->QueuePacket(action_packet);
|
CastToClient()->QueuePacket(action_packet);
|
||||||
if(caster->IsClient() && caster != this)
|
if(caster->IsClient() && caster != this)
|
||||||
|
|||||||
@ -2563,7 +2563,7 @@ void Mob::BardPulse(uint16 spell_id, Mob *caster) {
|
|||||||
cd->source = action->source;
|
cd->source = action->source;
|
||||||
cd->type = DamageTypeSpell;
|
cd->type = DamageTypeSpell;
|
||||||
cd->spellid = action->spell;
|
cd->spellid = action->spell;
|
||||||
cd->sequence = action->sequence;
|
cd->meleepush_xy = action->sequence;
|
||||||
cd->damage = 0;
|
cd->damage = 0;
|
||||||
if(!IsEffectInSpell(spell_id, SE_BindAffinity))
|
if(!IsEffectInSpell(spell_id, SE_BindAffinity))
|
||||||
{
|
{
|
||||||
@ -3827,7 +3827,7 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob* spelltar, bool reflect, bool use_r
|
|||||||
cd->source = action->source;
|
cd->source = action->source;
|
||||||
cd->type = action->type;
|
cd->type = action->type;
|
||||||
cd->spellid = action->spell;
|
cd->spellid = action->spell;
|
||||||
cd->sequence = action->sequence;
|
cd->meleepush_xy = action->sequence;
|
||||||
cd->damage = 0;
|
cd->damage = 0;
|
||||||
if(!IsEffectInSpell(spell_id, SE_BindAffinity))
|
if(!IsEffectInSpell(spell_id, SE_BindAffinity))
|
||||||
{
|
{
|
||||||
|
|||||||
@ -192,7 +192,7 @@ void Trap::Trigger(Mob* trigger)
|
|||||||
int dmg = zone->random.Int(effectvalue, effectvalue2);
|
int dmg = zone->random.Int(effectvalue, effectvalue2);
|
||||||
trigger->SetHP(trigger->GetHP() - dmg);
|
trigger->SetHP(trigger->GetHP() - dmg);
|
||||||
a->damage = dmg;
|
a->damage = dmg;
|
||||||
a->sequence = zone->random.Int(0, 1234567);
|
a->meleepush_xy = zone->random.Int(0, 1234567);
|
||||||
a->source = GetHiddenTrigger()!=nullptr ? GetHiddenTrigger()->GetID() : trigger->GetID();
|
a->source = GetHiddenTrigger()!=nullptr ? GetHiddenTrigger()->GetID() : trigger->GetID();
|
||||||
a->spellid = 0;
|
a->spellid = 0;
|
||||||
a->target = trigger->GetID();
|
a->target = trigger->GetID();
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user