mirror of
https://github.com/EQEmu/Server.git
synced 2025-12-12 09:31:30 +00:00
-Implemented the ability to properly use live spell projectile graphics.
This data is found in the player_1 field of the spells_new table. -Rule for this set to be disabled by default. -Enable IF your server uses an UF+ spell file and your players use UF+ clients -Otherwise your better off with alternative method/rules already implemented so that all players can see the effect. -Added ability for PERL ProjectileAnim function to only need an IT#### and not an actual item id. -If you want it in LUA somebody needs to add it. - Change to wizard innate critical ratios based on parse data.
This commit is contained in:
parent
8b2f325cd0
commit
35cd98c7a7
@ -1,10 +1,20 @@
|
|||||||
EQEMu Changelog (Started on Sept 24, 2003 15:50)
|
EQEMu Changelog (Started on Sept 24, 2003 15:50)
|
||||||
-------------------------------------------------------
|
-------------------------------------------------------
|
||||||
|
== 04/09/2014 ==
|
||||||
|
Kayen: Implemented ability to use the actual live spell projectile graphics that are defined in the modern spell file.
|
||||||
|
*This is disabled by default. Recommend enabling if your server uses an UF+ spell file AND most of your players use UF+ clients.
|
||||||
|
Kayen: Expanded the PERL ProjectileAnim(mob, item_id, [IsArrow?, speed, angle, tilt, arc, IDFile]) so you can now just set the weapon model graphic IT####
|
||||||
|
Example: ProjectileAnim($npc, 0, 0, 1, 0, 0, 0, "IT10747") This will shoot an SK 2.0 sword.
|
||||||
|
Kayen: Updated wizard innate critical damage modifier to be from 20-70% of base damage (based on live parses)
|
||||||
|
|
||||||
|
|
||||||
|
Optional SQL: utils/sql/git/optional/2014_04_09_SpellProjectileRule.sql
|
||||||
|
Note: This sql also contains a query to check if your spell file is compatible.
|
||||||
|
|
||||||
== 04/06/2014 ==
|
== 04/06/2014 ==
|
||||||
Uleat: Changed Mob::CanThisClassDualWield() behavior. This should let non-monk/beastlord dual-wielding classes attack with either fist as long as the other hand is occupied.
|
Uleat: Changed Mob::CanThisClassDualWield() behavior. This should let non-monk/beastlord dual-wielding classes attack with either fist as long as the other hand is occupied.
|
||||||
Notes:
|
Notes:
|
||||||
See this thread for more information and to provide feedback: http://www.eqemulator.org/forums/showthread.php?p=229328#post229328
|
See this thread for more information and to provide feedback: http://www.eqemulator.org/forums/showthread.php?p=229328#post229328
|
||||||
|
|
||||||
|
|
||||||
== 04/05/2014 ==
|
== 04/05/2014 ==
|
||||||
Akkadius: Fix for the Fix for the Fix: Rule Combat:OneProcPerWeapon was created so that you can revert to the original proc functionality
|
Akkadius: Fix for the Fix for the Fix: Rule Combat:OneProcPerWeapon was created so that you can revert to the original proc functionality
|
||||||
|
|||||||
@ -307,6 +307,7 @@ RULE_INT ( Spells, SuccorFailChance, 2) //Determines chance for a succor spell n
|
|||||||
RULE_INT ( Spells, FRProjectileItem_Titanium, 1113) // Item id for Titanium clients for Fire 'spell projectile'.
|
RULE_INT ( Spells, FRProjectileItem_Titanium, 1113) // Item id for Titanium clients for Fire 'spell projectile'.
|
||||||
RULE_INT ( Spells, FRProjectileItem_SOF, 80684) // Item id for SOF clients for Fire 'spell projectile'.
|
RULE_INT ( Spells, FRProjectileItem_SOF, 80684) // Item id for SOF clients for Fire 'spell projectile'.
|
||||||
RULE_INT ( Spells, FRProjectileItem_NPC, 80684) // Item id for NPC Fire 'spell projectile'.
|
RULE_INT ( Spells, FRProjectileItem_NPC, 80684) // Item id for NPC Fire 'spell projectile'.
|
||||||
|
RULE_BOOL ( Spells, UseLiveSpellProjectileGFX, false) // Use spell projectile graphics set in the spells_new table (player_1). Server must be using UF+ spell file.
|
||||||
RULE_CATEGORY_END()
|
RULE_CATEGORY_END()
|
||||||
|
|
||||||
RULE_CATEGORY( Combat )
|
RULE_CATEGORY( Combat )
|
||||||
|
|||||||
@ -1,3 +1,3 @@
|
|||||||
INSERT INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (1, 'Spells:FRProjectileItem_Titanium', '1113', 'Item id for Titanium clients for Fire spell projectile.');
|
INSERT INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (1, 'Spells:FRProjectileItem_Titanium', '1113', 'Item id for Titanium clients for Fire spell projectile.');
|
||||||
INSERT INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (1, 'Spells:FRProjectileItem_SOF', '80684', 'Item id for Titanium clients for Fire spell projectile.');
|
INSERT INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (1, 'Spells:FRProjectileItem_SOF', '80684', 'Item id for SOF clients for Fire spell projectile.');
|
||||||
INSERT INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (1, 'Spells:FRProjectileItem_NPC', '80684', 'Item id for Titanium clients for Fire spell projectile.');
|
INSERT INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (1, 'Spells:FRProjectileItem_NPC', '80684', 'Item id for NPC to use for Fire spell projectile.');
|
||||||
|
|||||||
@ -0,0 +1,7 @@
|
|||||||
|
-- Recommend enabling if your server uses an UF+ spell file and your players use UF+ client. This will give the proper graphics for all spell projectiles.
|
||||||
|
INSERT INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (1, 'Spells:UseLiveSpellProjectileGFX', false, ' Use spell projectile graphics set in the spells_new table (player_1). Server must be using UF+ spell file.');
|
||||||
|
|
||||||
|
-- Use this query to check if your spell file is compatible
|
||||||
|
-- If it returns in the player_1 field IT##### it will work.
|
||||||
|
SELECT id,name,player_1 from spells_new WHERE targettype = 1;
|
||||||
|
|
||||||
@ -79,7 +79,7 @@ int32 Client::GetActSpellDamage(uint16 spell_id, int32 value, Mob* target) {
|
|||||||
if (spell_id == SPELL_IMP_HARM_TOUCH) //Improved Harm Touch
|
if (spell_id == SPELL_IMP_HARM_TOUCH) //Improved Harm Touch
|
||||||
value -= GetAA(aaUnholyTouch) * 450; //Unholy Touch
|
value -= GetAA(aaUnholyTouch) * 450; //Unholy Touch
|
||||||
|
|
||||||
int chance = RuleI(Spells, BaseCritChance);
|
int chance = RuleI(Spells, BaseCritChance); //Wizard base critical chance is 2% (Does not scale with level)
|
||||||
chance += itembonuses.CriticalSpellChance + spellbonuses.CriticalSpellChance + aabonuses.CriticalSpellChance;
|
chance += itembonuses.CriticalSpellChance + spellbonuses.CriticalSpellChance + aabonuses.CriticalSpellChance;
|
||||||
|
|
||||||
chance += itembonuses.FrenziedDevastation + spellbonuses.FrenziedDevastation + aabonuses.FrenziedDevastation;
|
chance += itembonuses.FrenziedDevastation + spellbonuses.FrenziedDevastation + aabonuses.FrenziedDevastation;
|
||||||
@ -99,7 +99,7 @@ int32 Client::GetActSpellDamage(uint16 spell_id, int32 value, Mob* target) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
else if (GetClass() == WIZARD && (GetLevel() >= RuleI(Spells, WizCritLevel)) && (MakeRandomInt(1,100) <= RuleI(Spells, WizCritChance))) {
|
else if (GetClass() == WIZARD && (GetLevel() >= RuleI(Spells, WizCritLevel)) && (MakeRandomInt(1,100) <= RuleI(Spells, WizCritChance))) {
|
||||||
ratio += MakeRandomInt(1,100); //Wizard innate critical chance is calculated seperately from spell effect and is not a set ratio.
|
ratio += MakeRandomInt(20,70); //Wizard innate critical chance is calculated seperately from spell effect and is not a set ratio. (20-70 is parse confirmed)
|
||||||
Critical = true;
|
Critical = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -161,7 +161,7 @@ public:
|
|||||||
virtual void WearChange(uint8 material_slot, uint16 texture, uint32 color);
|
virtual void WearChange(uint8 material_slot, uint16 texture, uint32 color);
|
||||||
void DoAnim(const int animnum, int type=0, bool ackreq = true, eqFilterType filter = FilterNone);
|
void DoAnim(const int animnum, int type=0, bool ackreq = true, eqFilterType filter = FilterNone);
|
||||||
void ProjectileAnimation(Mob* to, int item_id, bool IsArrow = false, float speed = 0,
|
void ProjectileAnimation(Mob* to, int item_id, bool IsArrow = false, float speed = 0,
|
||||||
float angle = 0, float tilt = 0, float arc = 0);
|
float angle = 0, float tilt = 0, float arc = 0, const char *IDFile = nullptr);
|
||||||
void ChangeSize(float in_size, bool bNoRestriction = false);
|
void ChangeSize(float in_size, bool bNoRestriction = false);
|
||||||
inline uint8 SeeInvisible() const { return see_invis; }
|
inline uint8 SeeInvisible() const { return see_invis; }
|
||||||
inline bool SeeInvisibleUndead() const { return see_invis_undead; }
|
inline bool SeeInvisibleUndead() const { return see_invis_undead; }
|
||||||
|
|||||||
@ -6856,7 +6856,7 @@ XS(XS_Mob_ProjectileAnim); /* prototype to pass -Wmissing-prototypes */
|
|||||||
XS(XS_Mob_ProjectileAnim)
|
XS(XS_Mob_ProjectileAnim)
|
||||||
{
|
{
|
||||||
dXSARGS;
|
dXSARGS;
|
||||||
if (items < 3 || items > 8)
|
if (items < 3 || items > 9)
|
||||||
Perl_croak(aTHX_ "Usage: Mob::ProjectileAnim(THIS, mob, item_id, IsArrow?, speed, angle, tilt, arc)");
|
Perl_croak(aTHX_ "Usage: Mob::ProjectileAnim(THIS, mob, item_id, IsArrow?, speed, angle, tilt, arc)");
|
||||||
|
|
||||||
{
|
{
|
||||||
@ -6868,6 +6868,7 @@ XS(XS_Mob_ProjectileAnim)
|
|||||||
float angle = 0;
|
float angle = 0;
|
||||||
float tilt = 0;
|
float tilt = 0;
|
||||||
float arc = 0;
|
float arc = 0;
|
||||||
|
char * IDFile = nullptr;
|
||||||
|
|
||||||
if (sv_derived_from(ST(0), "Mob")) {
|
if (sv_derived_from(ST(0), "Mob")) {
|
||||||
IV tmp = SvIV((SV*)SvRV(ST(0)));
|
IV tmp = SvIV((SV*)SvRV(ST(0)));
|
||||||
@ -6903,7 +6904,9 @@ XS(XS_Mob_ProjectileAnim)
|
|||||||
arc = (float)SvNV(ST(7));
|
arc = (float)SvNV(ST(7));
|
||||||
}
|
}
|
||||||
|
|
||||||
THIS->ProjectileAnimation(mob, item_id, IsArrow, speed, angle, tilt, arc);
|
if (items > 8) { IDFile = (char *)SvPV_nolen(ST(8)); }
|
||||||
|
|
||||||
|
THIS->ProjectileAnimation(mob, item_id, IsArrow, speed, angle, tilt, arc, IDFile);
|
||||||
|
|
||||||
}
|
}
|
||||||
XSRETURN_EMPTY;
|
XSRETURN_EMPTY;
|
||||||
@ -8389,7 +8392,7 @@ XS(boot_Mob)
|
|||||||
newXSproto(strcpy(buf, "CheckLoS"), XS_Mob_CheckLoS, file, "$$");
|
newXSproto(strcpy(buf, "CheckLoS"), XS_Mob_CheckLoS, file, "$$");
|
||||||
newXSproto(strcpy(buf, "CheckLoSToLoc"), XS_Mob_CheckLoSToLoc, file, "$$$$;$");
|
newXSproto(strcpy(buf, "CheckLoSToLoc"), XS_Mob_CheckLoSToLoc, file, "$$$$;$");
|
||||||
newXSproto(strcpy(buf, "FindGroundZ"), XS_Mob_FindGroundZ, file, "$$$;$");
|
newXSproto(strcpy(buf, "FindGroundZ"), XS_Mob_FindGroundZ, file, "$$$;$");
|
||||||
newXSproto(strcpy(buf, "ProjectileAnim"), XS_Mob_ProjectileAnim, file, "$$$;$$$$$");
|
newXSproto(strcpy(buf, "ProjectileAnim"), XS_Mob_ProjectileAnim, file, "$$$;$$$$$$");
|
||||||
newXSproto(strcpy(buf, "HasNPCSpecialAtk"), XS_Mob_HasNPCSpecialAtk, file, "$$");
|
newXSproto(strcpy(buf, "HasNPCSpecialAtk"), XS_Mob_HasNPCSpecialAtk, file, "$$");
|
||||||
newXSproto(strcpy(buf, "SendAppearanceEffect"), XS_Mob_SendAppearanceEffect, file, "$$;$$$$");
|
newXSproto(strcpy(buf, "SendAppearanceEffect"), XS_Mob_SendAppearanceEffect, file, "$$;$$$$");
|
||||||
newXSproto(strcpy(buf, "SetFlyMode"), XS_Mob_SetFlyMode, file, "$$");
|
newXSproto(strcpy(buf, "SetFlyMode"), XS_Mob_SetFlyMode, file, "$$");
|
||||||
|
|||||||
@ -1346,7 +1346,7 @@ void Mob::SendItemAnimation(Mob *to, const Item_Struct *item, SkillUseTypes skil
|
|||||||
safe_delete(outapp);
|
safe_delete(outapp);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Mob::ProjectileAnimation(Mob* to, int item_id, bool IsArrow, float speed, float angle, float tilt, float arc) {
|
void Mob::ProjectileAnimation(Mob* to, int item_id, bool IsArrow, float speed, float angle, float tilt, float arc, const char *IDFile) {
|
||||||
|
|
||||||
const Item_Struct* item = nullptr;
|
const Item_Struct* item = nullptr;
|
||||||
uint8 item_type = 0;
|
uint8 item_type = 0;
|
||||||
@ -1380,6 +1380,10 @@ void Mob::ProjectileAnimation(Mob* to, int item_id, bool IsArrow, float speed, f
|
|||||||
arc = 50;
|
arc = 50;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char *item_IDFile = item->IDFile;
|
||||||
|
|
||||||
|
if (IDFile && (strncmp(IDFile, "IT", 2) == 0))
|
||||||
|
item_IDFile = IDFile;
|
||||||
|
|
||||||
// See SendItemAnimation() for some notes on this struct
|
// See SendItemAnimation() for some notes on this struct
|
||||||
EQApplicationPacket *outapp = new EQApplicationPacket(OP_SomeItemPacketMaybe, sizeof(Arrow_Struct));
|
EQApplicationPacket *outapp = new EQApplicationPacket(OP_SomeItemPacketMaybe, sizeof(Arrow_Struct));
|
||||||
@ -1393,7 +1397,7 @@ void Mob::ProjectileAnimation(Mob* to, int item_id, bool IsArrow, float speed, f
|
|||||||
as->item_id = item->ID;
|
as->item_id = item->ID;
|
||||||
as->item_type = item_type;
|
as->item_type = item_type;
|
||||||
as->skill = 0; // Doesn't seem to have any effect
|
as->skill = 0; // Doesn't seem to have any effect
|
||||||
strn0cpy(as->model_name, item->IDFile, 16);
|
strn0cpy(as->model_name, item_IDFile, 16);
|
||||||
as->velocity = speed;
|
as->velocity = speed;
|
||||||
as->launch_angle = angle;
|
as->launch_angle = angle;
|
||||||
as->tilt = tilt;
|
as->tilt = tilt;
|
||||||
@ -1406,7 +1410,6 @@ void Mob::ProjectileAnimation(Mob* to, int item_id, bool IsArrow, float speed, f
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void NPC::DoClassAttacks(Mob *target) {
|
void NPC::DoClassAttacks(Mob *target) {
|
||||||
if(target == nullptr)
|
if(target == nullptr)
|
||||||
return; //gotta have a target for all these
|
return; //gotta have a target for all these
|
||||||
|
|||||||
@ -3351,10 +3351,7 @@ void Mob::DoBuffTic(uint16 spell_id, int slot, uint32 ticsremaining, uint8 caste
|
|||||||
case SE_Root: {
|
case SE_Root: {
|
||||||
|
|
||||||
/* Root formula derived from extensive personal live parses - Kayen
|
/* Root formula derived from extensive personal live parses - Kayen
|
||||||
ROOT has a 40% chance to do a resist check to break.
|
ROOT has a 70% chance to do a resist check to break.
|
||||||
Resist check has NO LOWER bounds.
|
|
||||||
If multiple roots on target. Root in first slot will be checked first to break from nukes.
|
|
||||||
If multiple roots on target and broken by spell. Roots are removed ONE at a time in order of buff slot.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (MakeRandomInt(0, 99) < RuleI(Spells, RootBreakCheckChance)){
|
if (MakeRandomInt(0, 99) < RuleI(Spells, RootBreakCheckChance)){
|
||||||
@ -6064,26 +6061,35 @@ bool Mob::TrySpellProjectile(Mob* spell_target, uint16 spell_id){
|
|||||||
projectile_timer.Start(250);
|
projectile_timer.Start(250);
|
||||||
}
|
}
|
||||||
|
|
||||||
//Only use fire graphic for fire spells.
|
//This will use the correct graphic as defined in the player_1 field of spells_new table. Found in UF+ spell files.
|
||||||
if (spells[spell_id].resisttype == RESIST_FIRE) {
|
if (RuleB(Spells, UseLiveSpellProjectileGFX)) {
|
||||||
|
ProjectileAnimation(spell_target,0, false, 1.5,0,0,0, spells[spell_id].player_1);
|
||||||
if (IsClient()){
|
|
||||||
if (CastToClient()->GetClientVersionBit() <= 4) //Titanium needs alternate graphic.
|
|
||||||
ProjectileAnimation(spell_target,(RuleI(Spells, FRProjectileItem_Titanium)), false, 1.5);
|
|
||||||
else
|
|
||||||
ProjectileAnimation(spell_target,(RuleI(Spells, FRProjectileItem_SOF)), false, 1.5);
|
|
||||||
}
|
|
||||||
|
|
||||||
else
|
|
||||||
ProjectileAnimation(spell_target,(RuleI(Spells, FRProjectileItem_NPC)), false, 1.5);
|
|
||||||
|
|
||||||
if (spells[spell_id].CastingAnim == 64)
|
|
||||||
anim = 44; //Corrects for animation error.
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//Pending other types of projectile graphics. (They will function but with a default arrow graphic for now)
|
//This allows limited support for server using older spell files that do not contain data for bolt graphics.
|
||||||
else
|
else {
|
||||||
ProjectileAnimation(spell_target,0, 1, 1.5);
|
//Only use fire graphic for fire spells.
|
||||||
|
if (spells[spell_id].resisttype == RESIST_FIRE) {
|
||||||
|
|
||||||
|
if (IsClient()){
|
||||||
|
if (CastToClient()->GetClientVersionBit() <= 4) //Titanium needs alternate graphic.
|
||||||
|
ProjectileAnimation(spell_target,(RuleI(Spells, FRProjectileItem_Titanium)), false, 1.5);
|
||||||
|
else
|
||||||
|
ProjectileAnimation(spell_target,(RuleI(Spells, FRProjectileItem_SOF)), false, 1.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
ProjectileAnimation(spell_target,(RuleI(Spells, FRProjectileItem_NPC)), false, 1.5);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//Default to an arrow if not using a mage bolt (Use up to date spell file and enable above rules for best results)
|
||||||
|
else
|
||||||
|
ProjectileAnimation(spell_target,0, 1, 1.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (spells[spell_id].CastingAnim == 64)
|
||||||
|
anim = 44; //Corrects for animation error.
|
||||||
|
|
||||||
DoAnim(anim, 0, true, IsClient() ? FilterPCSpells : FilterNPCSpells); //Override the default projectile animation.
|
DoAnim(anim, 0, true, IsClient() ? FilterPCSpells : FilterNPCSpells); //Override the default projectile animation.
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user