-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:
KayenEQ
2014-04-09 05:17:36 -04:00
parent 8b2f325cd0
commit 35cd98c7a7
9 changed files with 64 additions and 34 deletions
+2 -2
View File
@@ -79,7 +79,7 @@ int32 Client::GetActSpellDamage(uint16 spell_id, int32 value, Mob* target) {
if (spell_id == SPELL_IMP_HARM_TOUCH) //Improved Harm 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.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))) {
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;
}
+1 -1
View File
@@ -161,7 +161,7 @@ public:
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 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);
inline uint8 SeeInvisible() const { return see_invis; }
inline bool SeeInvisibleUndead() const { return see_invis_undead; }
+6 -3
View File
@@ -6856,7 +6856,7 @@ XS(XS_Mob_ProjectileAnim); /* prototype to pass -Wmissing-prototypes */
XS(XS_Mob_ProjectileAnim)
{
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)");
{
@@ -6868,6 +6868,7 @@ XS(XS_Mob_ProjectileAnim)
float angle = 0;
float tilt = 0;
float arc = 0;
char * IDFile = nullptr;
if (sv_derived_from(ST(0), "Mob")) {
IV tmp = SvIV((SV*)SvRV(ST(0)));
@@ -6903,7 +6904,9 @@ XS(XS_Mob_ProjectileAnim)
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;
@@ -8389,7 +8392,7 @@ XS(boot_Mob)
newXSproto(strcpy(buf, "CheckLoS"), XS_Mob_CheckLoS, file, "$$");
newXSproto(strcpy(buf, "CheckLoSToLoc"), XS_Mob_CheckLoSToLoc, 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, "SendAppearanceEffect"), XS_Mob_SendAppearanceEffect, file, "$$;$$$$");
newXSproto(strcpy(buf, "SetFlyMode"), XS_Mob_SetFlyMode, file, "$$");
+6 -3
View File
@@ -1346,7 +1346,7 @@ void Mob::SendItemAnimation(Mob *to, const Item_Struct *item, SkillUseTypes skil
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;
uint8 item_type = 0;
@@ -1380,6 +1380,10 @@ void Mob::ProjectileAnimation(Mob* to, int item_id, bool IsArrow, float speed, f
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
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_type = item_type;
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->launch_angle = angle;
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) {
if(target == nullptr)
return; //gotta have a target for all these
+28 -22
View File
@@ -3351,10 +3351,7 @@ void Mob::DoBuffTic(uint16 spell_id, int slot, uint32 ticsremaining, uint8 caste
case SE_Root: {
/* Root formula derived from extensive personal live parses - Kayen
ROOT has a 40% 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.
ROOT has a 70% chance to do a resist check to break.
*/
if (MakeRandomInt(0, 99) < RuleI(Spells, RootBreakCheckChance)){
@@ -6064,26 +6061,35 @@ bool Mob::TrySpellProjectile(Mob* spell_target, uint16 spell_id){
projectile_timer.Start(250);
}
//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);
if (spells[spell_id].CastingAnim == 64)
anim = 44; //Corrects for animation error.
//This will use the correct graphic as defined in the player_1 field of spells_new table. Found in UF+ spell files.
if (RuleB(Spells, UseLiveSpellProjectileGFX)) {
ProjectileAnimation(spell_target,0, false, 1.5,0,0,0, spells[spell_id].player_1);
}
//Pending other types of projectile graphics. (They will function but with a default arrow graphic for now)
else
ProjectileAnimation(spell_target,0, 1, 1.5);
//This allows limited support for server using older spell files that do not contain data for bolt graphics.
else {
//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.
return true;