That framework use the “rewritten” library I did from NWN2 and many little usefull functions I did, It would require a big directory upload with many check on depedencies for it to be functionnal, it’s completly tied to our campaign. But I can I can give you the core as exemple :
//dmr081520: Various things to assist with making cutscenes
void playAnimation(object oTarget, string sAnim, int nLoop=FALSE)
{
PlayCustomAnimation(oTarget, sAnim, nLoop);
}
float conjureAnimDelay()
{
return 1.1;
}
float castAnimDelay()
{
return 2.1;
}
float castDelay() //Delay before the projectile is spawned
{
return 0.7;
}
int vfx_teleport()
{
return 1059;
}
int vfx_bloodspurt()
{
return 1060;
}
int vfx_abjuration_conjure()
{
return 1061;
}
int vfx_abjuration_cast()
{
return 1062;
}
int vfx_sonic_conjure()
{
return 1063;
}
int vfx_sonic_cast()
{
return 1064;
}
int vfx_wailofbanshee()
{
return 1065;
}
int vfx_evocation_conjure()
{
return 1066;
}
int vfx_evocation_cast()
{
return 1067;
}
int vfx_evocation_aoe()
{
return 1068;
}
int vfx_transmutation_conjure()
{
return 1069;
}
int vfx_transmutation_cast()
{
return 1070;
}
int vfx_fire_conjure()
{
return 1071;
}
int vfx_fire_cast()
{
return 1072;
}
int vfx_fire_aoe()
{
return 1073;
}
int vfx_cacophonicburst()
{
return 1074;
}
int vfx_ice_aoe()
{
return 1075;
}
int vfx_lightning_conjure()
{
return 1076;
}
int vfx_lightning_cast()
{
return 1077;
}
int vfx_fire_hit()
{
return 1078;
}
int vfx_sonic_hit()
{
return 1079;
}
int vfx_acid_hit()
{
return 1080;
}
int vfx_necromancy_conjure()
{
return 1081;
}
int vfx_necromany_cast()
{
return 1082;
}
int vfx_meteorswarm_impact()
{
return 1083;
}
int vfx_enchantment_conjure()
{
return 1084;
}
int vfx_enchantment_cast()
{
return 1085;
}
int vfx_stone_explosion()
{
return 1086;
}
int vfx_screenshake_short()
{
return 1087;
}
int vfx_magicmissile_impact()
{
return 1088;
}
int vfx_conjuration_conjure()
{
return 1089;
}
int vfx_conjuration_cast()
{
return 1090;
}
int vfx_glacialwrath_effect()
{
return 1091;
}
int vfx_stoneskin_effect()
{
return 1092;
}
int vfx_glacialwrath_cone()
{
return 1093;
}
int vfx_ambient_fade()
{
return 1096;
}
The Idea is to have all the animations and timers/delay associated with them so you won’ t have to manually put the right number each time.
#include "fct_cutscene_anim"
#include "fct_soarscript"
void main()
{
object oIrenicus = GetObjectByTag("csiren");
object oImoen = GetObjectByTag("csimoen");
object oCowled1 = GetObjectByTag("ccowled1");
object oCowled2 = GetObjectByTag("ccowled2");
object oCowled3 = GetObjectByTag("ccowled3");
object oCowled4 = GetObjectByTag("ccowled4");
location lIrenicus = GetLocation(oIrenicus);
location lImoen = GetLocation(oImoen);
location lCowled1 = GetLocation(oCowled1);
location lCowled2 = GetLocation(oCowled2);
location lCowled3 = GetLocation(oCowled3);
location lCowled4 = GetLocation(oCowled4);
float fAnimBuffer = 0.5;
effect eAbjConjure = EffectVisualEffect(vfx_abjuration_conjure());
effect eAbjCast = EffectVisualEffect(vfx_abjuration_cast());
effect eConConjure = EffectVisualEffect(vfx_conjuration_conjure());
effect eConCast = EffectVisualEffect(vfx_conjuration_cast());
effect eLigConjure = EffectVisualEffect(vfx_lightning_conjure());
effect eLigCast = EffectVisualEffect(vfx_lightning_cast());
effect eTraConjure = EffectVisualEffect(vfx_transmutation_conjure());
effect eTraCast = EffectVisualEffect(vfx_transmutation_cast());
/*****************************************************************/
//IRENICUS begins to cast Wail of the Banshee
object oBansheeTarget = GetWaypointByTag("wp_BansheeTarget");
location lBansheeTarget = GetLocation(oBansheeTarget);
effect eConjure = EffectVisualEffect(vfx_sonic_conjure());
effect eCast = EffectVisualEffect(vfx_sonic_cast());
object oSFXBanshee = GetObjectByTag("sound_cutscene_banshee");
playAnimation(oIrenicus, "mjr_conjure", FALSE);
ApplyEffectToObject(DURATION_TYPE_INSTANT, eConjure, oIrenicus);
DelayCommand(conjureAnimDelay(), playAnimation(oIrenicus, "mjr_cast", FALSE));
DelayCommand(conjureAnimDelay(), ApplyEffectToObject(DURATION_TYPE_INSTANT, eCast, oIrenicus));
DelayCommand(conjureAnimDelay() + castDelay(), SpawnSpellProjectile(oIrenicus, oBansheeTarget, lIrenicus, lBansheeTarget, SPELL_WAIL_OF_THE_BANSHEE, PROJECTILE_PATH_TYPE_HIGH_BALLISTIC));
DelayCommand(conjureAnimDelay() + castDelay(), SoundObjectPlay(oSFXBanshee));
DelayCommand(conjureAnimDelay() + castAnimDelay(), playAnimation(oIrenicus, "idleM", TRUE));
/*****************************************************************/
//COWLED 1 and 4 are killed by Wail of the Banshee
float fDelay = GetProjectileTravelTime(lIrenicus, lBansheeTarget, PROJECTILE_PATH_TYPE_HIGH_BALLISTIC, SPELL_WAIL_OF_THE_BANSHEE);
fDelay = fDelay + conjureAnimDelay() + castDelay();
effect eProjHit = EffectVisualEffect(VFX_HIT_SPELL_WAIL_OF_THE_BANSHEE);
effect eImpact = EffectVisualEffect(VFX_HIT_SPELL_NECROMANCY);
effect eDeath = EffectDeath(FALSE, FALSE, TRUE, FALSE);
DelayCommand(fDelay, ApplyEffectAtLocation(DURATION_TYPE_INSTANT, eProjHit, lBansheeTarget));
fDelay = fDelay + 0.5;
DelayCommand(fDelay, ApplyEffectToObject(DURATION_TYPE_INSTANT, eImpact, oCowled1));
DelayCommand(fDelay, ApplyEffectToObject(DURATION_TYPE_INSTANT, eImpact, oCowled4));
DelayCommand(fDelay, ApplyEffectToObject(DURATION_TYPE_INSTANT, eDeath, oCowled1));
DelayCommand(fDelay, ApplyEffectToObject(DURATION_TYPE_INSTANT, eDeath, oCowled4));
/*****************************************************************/
//COWLED1 play animations to being combat
float fDelayC1 = 0.8;
DelayCommand(fDelayC1, playAnimation(oCowled1, "idleM", TRUE));
fDelayC1 = fDelayC1 + fAnimBuffer;
DelayCommand(fDelayC1, playAnimation(oCowled1, "def_conjure"));
DelayCommand(fDelayC1, ApplyEffectAtLocation(DURATION_TYPE_INSTANT, eAbjConjure, lCowled1));
/*****************************************************************/
//COWLED2 play animations to being combat
float fDelayC2 = 2.0;
DelayCommand(fDelayC2, playAnimation(oCowled2, "idleM", TRUE));
fDelayC2 = fDelayC2 + fAnimBuffer;
DelayCommand(fDelayC2, playAnimation(oCowled2, "atk_conjure"));
DelayCommand(fDelayC2, ApplyEffectAtLocation(DURATION_TYPE_INSTANT, eTraConjure, lCowled2));
fDelayC2 = fDelayC2 + conjureAnimDelay();
DelayCommand(fDelayC2, playAnimation(oCowled2, "atk_cast"));
DelayCommand(fDelayC2, ApplyEffectAtLocation(DURATION_TYPE_INSTANT, eTraCast, lCowled2));
/*****************************************************************/
//COWLED3 play animations to being combat
float fDelayC3 = 1.7;
DelayCommand(fDelayC3, playAnimation(oCowled3, "idleM", TRUE));
fDelayC3 = fDelayC3 + fAnimBuffer;
DelayCommand(fDelayC3, playAnimation(oCowled3, "atk_conjure"));
DelayCommand(fDelayC3, ApplyEffectAtLocation(DURATION_TYPE_INSTANT, eLigConjure, lCowled3));
fDelayC3 = fDelayC3 + conjureAnimDelay();
DelayCommand(fDelayC3, playAnimation(oCowled3, "atk_cast"));
DelayCommand(fDelayC3, ApplyEffectAtLocation(DURATION_TYPE_INSTANT, eLigCast, lCowled3));
/*****************************************************************/
//COWLED4 play animations to being combat
float fDelayC4 = 1.0;
DelayCommand(fDelayC4, playAnimation(oCowled4, "idleM", TRUE));
fDelayC4 = fDelayC4 + fAnimBuffer;
DelayCommand(fDelayC4, playAnimation(oCowled4, "gen_conjure"));
DelayCommand(fDelayC4, ApplyEffectAtLocation(DURATION_TYPE_INSTANT, eConConjure, lCowled4));
/*****************************************************************/
//IMOEN casts Orb of Sound at IRENICUS
effect eOrbConjure = EffectVisualEffect(vfx_conjuration_conjure());
effect eOrbCast = EffectVisualEffect(vfx_conjuration_cast());
float fDelay2 = 2.0;
DelayCommand(fDelay2, playAnimation(oImoen, "atk_conjure", FALSE));
DelayCommand(fDelay2, ApplyEffectAtLocation(DURATION_TYPE_INSTANT, eOrbConjure, lImoen));
fDelay2 = fDelay2 + conjureAnimDelay();
DelayCommand(fDelay2, playAnimation(oImoen, "atk_cast", FALSE));
DelayCommand(fDelay2, ApplyEffectAtLocation(DURATION_TYPE_INSTANT, eOrbCast, lImoen));
}
the approach we are using is of many scripts that are tied together with a conversation, where each line is an event of the cutscne with a static camera to shows it.
You don’ t do this in one go, you start to set the stage, then the first event, and so on. and you finish the last event and release/clean the stage.
And after, you come back at it to fix things that aren’t as you wish them to be or don 't behave as you want. It’s a lot of work. Also NWN2 tools aren’t that great for cutscenes when you compare them to dragon age origin for exemple. NWN2 is more powerfull for game events, but less powerfull for “visuals”.
For that mod we also have the luck to be 2 able to script, it allows “multiple pass” with ideas that complete each others.