Warning: Big post. Make a sandwich, get a drink, this is gonna take awhile for me to explain and you to absorb. If adding custom efefcts to your mobs and gear isn't your thing, you should save yourself the time and skip reading this.
Big fat important disclaimer notice:
Back your stuff up! I will not be held responsible for you screwing up your server. Absolutely do not pester the darkstar devs with bugs caused by attempts to make custom things, especially from the info in this post, or expect them to fix it. If you have trouble figuring out how to do something I'm willing to try and help you, but if people make this a hassle for either the DSP devs or myself, I'm more likely to erase/blank my post, capeesh? And if anyone wants to thank me, find something not working and fix it. The older the expansion it comes from the better.
I'm providing some example code here. This is custom content, so it hasn't gone into a pull request.
First, lets start with enabling the currently unused animations for spikes that don't exist!
(Earth, wind, and water element spike animations.)
You can also trigger counter/retaliation animations this way, which I'm doing in my examples.
In battelentity.h find the enumeration for SUBEFFECT, and add this line:
Code: Select all
SUBEFFECT_DELUGE_SPIKES = 9,
In battleutils.cpp you need a case entry in HandleSpikesDamage in the switch statement if you intent to do an actual status effect or scripted mob spikes using your new animation. You see:
Code: Select all
switch (Action->spikesEffect)
{
case SPIKE_BLAZE:
case SPIKE_ICE:
case SPIKE_SHOCK:
PAttacker->addHP(-Action->spikesParam);
break;
case SPIKE_DREAD:
}
Code: Select all
break;
case SPIKE_DELUGE:
PAttacker->addHP(-Action->spikesParam);
break;
Code: Select all
if (((CItemArmor*)PItem)->getModifier(MOD_ITEM_SPIKES_TYPE) > 0 && ((CItemArmor*)PItem)->getModifier(MOD_ITEM_SPIKES_TYPE) < 7)
Code: Select all
if (((CItemArmor*)PItem)->getModifier(MOD_ITEM_SPIKES_TYPE) > 0 && (((CItemArmor*)PItem)->getModifier(MOD_ITEM_SPIKES_TYPE) < 11 || ((CItemArmor*)PItem)->getModifier(MOD_ITEM_SPIKES_TYPE) == 63))
Code: Select all
// Earring (1)
PItem = PCharDef->getEquip(SLOT_EAR1);
if (PItem)
{
Action->spikesEffect = (SUBEFFECT)0;
if (((CItemArmor*)PItem)->getModifier(MOD_ITEM_SPIKES_TYPE) > 0 && (((CItemArmor*)PItem)->getModifier(MOD_ITEM_SPIKES_TYPE) < 11 || ((CItemArmor*)PItem)->getModifier(MOD_ITEM_SPIKES_TYPE) == 63))
{
Action->spikesEffect = (SUBEFFECT)((CItemArmor*)PItem)->getModifier(MOD_ITEM_SPIKES_TYPE);
}
Action->spikesParam = ((CItemArmor*)PItem)->getModifier(MOD_ITEM_SPIKES_DMG);
chance = ((CItemArmor*)PItem)->getModifier(MOD_ITEM_SPIKES_CHANCE);
if (Action->spikesEffect && HandleSpikesEquip(PAttacker, PDefender, Action, Action->spikesParam, Action->spikesEffect, chance))
return true;
}
// Earring (2)
PItem = PCharDef->getEquip(SLOT_EAR2);
if (PItem)
{
Action->spikesEffect = (SUBEFFECT)0;
if (((CItemArmor*)PItem)->getModifier(MOD_ITEM_SPIKES_TYPE) > 0 && (((CItemArmor*)PItem)->getModifier(MOD_ITEM_SPIKES_TYPE) < 11 || ((CItemArmor*)PItem)->getModifier(MOD_ITEM_SPIKES_TYPE) == 63))
{
Action->spikesEffect = (SUBEFFECT)((CItemArmor*)PItem)->getModifier(MOD_ITEM_SPIKES_TYPE);
}
Action->spikesParam = ((CItemArmor*)PItem)->getModifier(MOD_ITEM_SPIKES_DMG);
chance = ((CItemArmor*)PItem)->getModifier(MOD_ITEM_SPIKES_CHANCE);
if (Action->spikesEffect && HandleSpikesEquip(PAttacker, PDefender, Action, Action->spikesParam, Action->spikesEffect, chance))
return true;
}
Now what if we want a status effect, like how shock spikes do stun? To do that, we need to modify HandleSpikesStatusEffect with another "case" after the previous case break, but before the default, like so:
Code: Select all
break;
}
case SUBEFFECT_DELUGE_SPIKES: // Currently unused in retail
{
if(WELL512::irand()%100 <= 25+lvlDiff && PAttacker->StatusEffectContainer->HasStatusEffect(EFFECT_ATTACK_DOWN) == false)
{
PAttacker->StatusEffectContainer->AddStatusEffect(new CStatusEffect(EFFECT_ATTACK_DOWN, EFFECT_ATTACK_DOWN, 20, 0, 30));
}
break;
}
default:
Now you may notice that dread spikes when assigned to equipment, isn't working. This is because there is no item in retail that does this, so that functionality was never coded into HandleSpikesEquip but don't worry, we can fix that easy peezy, and add TP for our fake retaliation procs on gear (counter spikes) there while we're at it, if you do a spike case for that back where we did with deluge spikes:
Code: Select all
bool HandleSpikesEquip(CBattleEntity* PAttacker, CBattleEntity* PDefender, apAction_t* Action, uint8 damage, SUBEFFECT spikesType, uint8 chance)
{
int lvlDiff = dsp_cap((PDefender->GetMLevel() - PAttacker->GetMLevel()), -5, 5)*2;
if(WELL512::irand()%100 <= chance+lvlDiff)
{
// Spikes landed
if(spikesType == SUBEFFECT_CURSE_SPIKES)
{
Action->spikesMessage = 0; // Log says nothing?
Action->spikesParam = EFFECT_CURSE_I;
}
else if(spikesType == SUBEFFECT_DREAD_SPIKES)
{
if (PAttacker->m_EcoSystem == SYSTEM_UNDEAD)
{
// Doesn't work on undead!
Action->spikesMessage = 0;
Action->spikesEffect = (SUBEFFECT)0;
Action->spikesParam = 0;
// Why is this STILL animating on undead mobs???
return false;
}
else
{
uint8 ratio = dsp_cap((float)damage/4, 1, 255);
Action->spikesMessage = 132;
Action->spikesParam = HandleStoneskin(PAttacker, damage - WELL512::irand()%ratio + WELL512::irand()%ratio);
PDefender->addHP(Action->spikesParam);
PAttacker->addHP(-Action->spikesParam);
}
}
else if(spikesType == SUBEFFECT_COUNTER)
{
uint8 ratio = dsp_cap((float)damage/4, 1, 255);
Action->spikesParam = HandleStoneskin(PAttacker, damage - WELL512::irand()%ratio + WELL512::irand()%ratio);
PAttacker->addHP(-Action->spikesParam);
// PDefender->addTP(PDefender->GetWeaponDelay(true) / some_number? );
PDefender->addTP(1);
}
else
{
uint8 ratio = dsp_cap((float)damage/4, 1, 255);
Action->spikesParam = HandleStoneskin(PAttacker, damage - WELL512::irand()%ratio + WELL512::irand()%ratio);
PAttacker->addHP(-Action->spikesParam);
}
return true;
}
return false;
}
Want a mob that has it as a spell? Well thats a bit more involved. And I think I'll have to save making custom dummy entries in the spells table for another day. I can show you how to do the effect though. I have a few custom superbad NMs that get custom spikes as part of their TP moves (I beefed up some old NMs like Simurg, Roc, and LumberJack). Here is "Duluge Spikes" as a status effect:
Code: Select all
require("scripts/globals/status");
-----------------------------------
-- onEffectGain Action
-----------------------------------
function onEffectGain(target,effect)
target:addMod(MOD_SPIKES,9);
target:addMod(MOD_SPIKES_DMG, effect:getPower());
end;
-----------------------------------
-- onEffectTick Action
-----------------------------------
function onEffectTick(target,effect)
end;
-----------------------------------
-- onEffectLose Action
-----------------------------------
function onEffectLose(target,effect)
target:delMod(MOD_SPIKES,9);
target:delMod(MOD_SPIKES_DMG, effect:getPower());
end;
If you create other custom effects, you are going to need to add them in status.lua and status_effect.h, as well as status_effects.sql, and call them using addStatusEffectEx() instead of addStatusEffect() so you can dummy another icon and help text onto them. I suggest using "damage spikes" for your piggybacking needs.
It is also possible to make multiple effects that use the same animation if you are creative.
You can split curse spikes into one that does curse and no damage, and one that does darkness damage and a different effect.
I have a light element spike that gives you small amounts of mp, hidden away one of my items waiting for a lucky player to discover it, and it is not just reprisal with mp or a mini Ochain, nor is it aspir spikes.
With a little (ok, a lot..) of extra work, you can do all this stuff to teh weapon additional effects as well, without having to script every item, and even stuff them into custom augment table entries to boot.
Which reminds me... Don't try to place spike effects onto you main weapon, subweapon, ranged or ammo gear. Shields are the only thing that goes into one of those slots that you can safely stuff spikes onto without having to edit the source further to kill potential crashbugs. Stick to actual armor pieces.
It is also worth mentioning that its very easy to overpower gear this way, even with short duration effects or small damage amounts.
<.<
>.>
Man...Google image search has a really crappy selection of "spikes everywhere" meme material.