Initial commit

Adding all of the current content for Anphillia Unlimited.
This commit is contained in:
Jaysyn904
2024-01-04 07:49:38 -05:00
parent df18cd54c8
commit 28cdb617b3
12943 changed files with 9727121 additions and 0 deletions

View File

@@ -0,0 +1,285 @@
#include "util_inc"
#include "dbg_inc"
#include "spell_inc"
#include "nwnx_creature"
#include "nw_i0_spells"
object GetClosestMissileTarget(location lTarget)
{
int nth = 1;
object oTarget;
while (1)
{
oTarget = GetNearestCreatureToLocation(CREATURE_TYPE_IS_ALIVE, TRUE, lTarget, nth++);
if (oTarget == OBJECT_INVALID)
return oTarget;
if (GetPlotFlag(oTarget) || oTarget == OBJECT_SELF || !GetObjectSeen(oTarget) || !GetIsEnemy(oTarget))
continue;
if (GetDistanceBetweenLocations(lTarget, GetLocation(oTarget)) <= RADIUS_SIZE_GARGANTUAN)
return oTarget;
else
return OBJECT_INVALID;
}
return OBJECT_INVALID;
}
struct missiles
{
int vfx;
int vfximpact;
int count;
int numdice;
int whichdice;
int dmgmod;
int dmgtype;
int continous;
};
struct missiles GetMissiles(int nSpellId, object oCaster, int nMetaMagic)
{
struct missiles m;
int nCasterLevel = GetCasterLevel(oCaster);
switch (nSpellId)
{
case SPELL_MAGIC_MISSILE:
case SPELL_SHADOW_CONJURATION_MAGIC_MISSILE:
m.vfx = VFX_IMP_MIRV;
m.vfximpact = VFX_IMP_MAGBLUE;
m.count = min((1+nCasterLevel)/2, 5);
m.numdice = 1;
m.whichdice = 4;
m.dmgmod = 1;
m.dmgtype = DAMAGE_TYPE_MAGICAL;
m.continous = 0;
break;
case SPELL_ISAACS_LESSER_MISSILE_STORM:
m.vfx = VFX_IMP_MIRV;
m.vfximpact = VFX_IMP_MAGBLUE;
m.count = min(nCasterLevel, 10);
m.numdice = 1;
m.whichdice = 6;
m.dmgmod = 0;
m.dmgtype = DAMAGE_TYPE_MAGICAL;
m.continous = 0;
break;
case SPELL_ISAACS_GREATER_MISSILE_STORM:
m.vfx = VFX_IMP_MIRV;
m.vfximpact = VFX_IMP_MAGBLUE;
m.count = min(nCasterLevel, 20);
m.numdice = 2;
m.whichdice = 6;
m.dmgmod = 0;
m.dmgtype = DAMAGE_TYPE_MAGICAL;
m.continous = 0;
break;
case SPELL_BALL_LIGHTNING:
m.vfx = VFX_IMP_MIRV_ELECTRIC;
m.vfximpact = VFX_IMP_LIGHTNING_S;
m.count = min(nCasterLevel, 15);
m.numdice = 1;
m.whichdice = 6;
m.dmgmod = 0;
m.dmgtype = DAMAGE_TYPE_ELECTRICAL;
m.continous = 0;
break;
case SPELL_FLAME_ARROW:
m.vfx = VFX_IMP_MIRV_FLAME;
m.vfximpact = VFX_IMP_FLAME_S;
m.count = (3+nCasterLevel)/4;
m.numdice = 4;
m.whichdice = 6;
m.dmgmod = 1;
m.dmgtype = DAMAGE_TYPE_FIRE;
m.continous = 0;
break;
case SPELL_FIREBRAND:
m.vfx = VFX_IMP_MIRV_FLAME;
m.vfximpact = VFX_IMP_FLAME_M;
m.count = min(nCasterLevel, 15);
m.numdice = 1;
m.whichdice = 6;
m.dmgmod = nCasterLevel;
m.dmgtype = DAMAGE_TYPE_FIRE;
m.continous = 0;
break;
case SPELL_MELFS_ACID_ARROW:
case SPELL_GREATER_SHADOW_CONJURATION_ACID_ARROW:
m.vfx = VFX_DUR_MIRV_ACID;
m.vfximpact = VFX_IMP_ACID_L;
m.count = 1;
m.numdice = 3;
m.whichdice = 6;
m.dmgmod = 0;
m.dmgtype = DAMAGE_TYPE_ACID;
m.continous = 1 + (2+nCasterLevel)/3;
break;
default:
dbg_ReportBug("Spell " + IntToString(nSpellId) + " calling into missile script", OBJECT_SELF);
break;
}
return m;
}
int ApplyMissilesToTarget(object oCaster, object oTarget, struct missiles m, int nMetaMagic, int nMissiles=-1)
{
if (nMissiles != -1)
m.count = nMissiles;
if (m.count == 0)
return 0;
effect eMissile = EffectVisualEffect(m.vfx);
effect eVis = EffectVisualEffect(m.vfximpact);
int nHits = 0, nCrits = 0, i, d;
float fDist = GetDistanceBetween(oCaster, oTarget);
float fDelay = fDist / (3.0 * log(fDist) + 2.0);
int nCasterBonus = 0;
int nSpellSchool = spell_GetSchool(GetSpellId());
nCasterBonus += GetHasFeat(spell_GetSpellFocusFeat(nSpellSchool), oCaster)*2;
nCasterBonus += GetHasFeat(spell_GetSpellFocusFeat(nSpellSchool, TRUE), oCaster)*3;
nCasterBonus += GetHasFeat(FEAT_COMBAT_CASTING, oCaster)*4;
nCasterBonus += GetLocalInt(oCaster, "SPELL_MISSILE_ATTACK_BOUNS");
int nOldBab = GetBaseAttackBonus(oCaster);
NWNX_Creature_SetBaseAttackBonus(oCaster, nOldBab + nCasterBonus);
for (i = 0; i < m.count; i++)
{
// try to hit.
int nAttackResult = TouchAttackRanged(oTarget, TRUE);
if (nAttackResult && !MyResistSpell(oCaster, oTarget, fDelay))
{
int nDamage = m.dmgmod;
if (nMetaMagic == METAMAGIC_MAXIMIZE)
{
nDamage += m.numdice * m.whichdice;
}
else
{
for (d = 0; d < m.numdice; d++)
nDamage += Random(m.whichdice)+1;
}
if (nAttackResult == 2)
nDamage *= 2;
if (nMetaMagic == METAMAGIC_EMPOWER)
nDamage = FloatToInt(1.5 * nDamage);
//Apply the MIRV and damage effect
effect eDam = EffectDamage(nDamage, m.dmgtype);
DelayCommand(fDelay+0.1, ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eVis, oTarget));
DelayCommand(0.1, ApplyEffectToObject(DURATION_TYPE_INSTANT, eMissile, oTarget));
DelayCommand(fDelay+0.1, ApplyEffectToObject(DURATION_TYPE_INSTANT, eDam, oTarget));
}
else if (nAttackResult > 0) // Resisted
{
ApplyEffectToObject(DURATION_TYPE_INSTANT, eMissile, oTarget);
}
else // missed
{
vector v = GetPosition(oTarget);
v.x += IntToFloat(Random(100)-50)/25.0;
v.y += IntToFloat(Random(100)-50)/25.0;
ApplyEffectAtLocation(DURATION_TYPE_INSTANT, eMissile, Location(GetArea(oTarget), v, 0.0));
}
nHits += nAttackResult == 1;
nCrits += nAttackResult == 2;
}
SignalEvent(oTarget, EventSpellCastAt(oCaster, GetSpellId()));
NWNX_Creature_SetBaseAttackBonus(oCaster, nOldBab);
return nCrits << 16 | nHits;
}
void main()
{
object oCaster = OBJECT_SELF;
object oTarget = GetSpellTargetObject();
location lTarget = GetSpellTargetLocation();
int nSpell = GetSpellId();
int nMetaMagic = GetMetaMagicFeat();
if (GetIsObjectValid(oTarget))
oTarget = GetClosestMissileTarget(lTarget);
if (oTarget == OBJECT_INVALID)
{
FloatingTextStringOnCreature("You cannot see a valid target in range", oCaster, FALSE);
return;
}
struct missiles m = GetMissiles(nSpell, oCaster, nMetaMagic);
if (GetObjectType(oTarget) != OBJECT_TYPE_CREATURE)
{
ApplyMissilesToTarget(oCaster, oTarget, m, nMetaMagic);
return;
}
int nMissiles = m.count/2; // At least half of all missiles always go to primary target
int nResults = ApplyMissilesToTarget(oCaster, oTarget, m, nMetaMagic, nMissiles);
// For the rest, keep applying to nearby targets until we run out of missiles
nMissiles = m.count - nMissiles;
int nth = 1;
while (nMissiles > 0)
{
oTarget = GetNearestCreatureToLocation(CREATURE_TYPE_IS_ALIVE, TRUE, lTarget, nth++);
if (oTarget == OBJECT_INVALID)
{
nth = 1;
continue;
}
if (GetPlotFlag(oTarget) || oTarget == oCaster || !GetObjectSeen(oTarget, oCaster) || !GetIsEnemy(oTarget, oCaster))
continue;
if (GetDistanceBetweenLocations(lTarget, GetLocation(oTarget)) <= RADIUS_SIZE_GARGANTUAN)
{
nResults += ApplyMissilesToTarget(oCaster, oTarget, m, nMetaMagic, 1);
nMissiles--;
}
else
nth = 1;
}
// Display the hit data
int nHits = nResults & 0xFFFF;
int nCrits = nResults >> 16;
int nMisses = m.count - nHits - nCrits;
string sHitString = "You scored ";
int bCrits = nCrits > 0;
int bHits = nHits > 0;
int bMisses = nMisses > 0;
if (bHits || bCrits)
{
sHitString += IntToString(nCrits + nHits);
if (!bHits)
sHitString += " criticals";
else
sHitString += " hits";
if (bHits && bCrits)
sHitString += " (" + IntToString(nCrits) + " criticals)";
}
if (bMisses)
{
if (bHits || bCrits)
sHitString += " and ";
sHitString += IntToString(nMisses) + " misses";
}
DelayCommand(2.0, SendMessageToPC(oCaster, sHitString));
}