Game Development Community

dev|Pro Game Development Curriculum

afxRemix: Hellfire & Brimstone

by Gibby · 01/12/2013 (10:47 am) · 5 comments

Well it's been a couple of years, but here's another afxRemix. This one borrows heavily from Steven Acaster's CoD Minefield Triggers and stitches pieces of five spells together.

To use, create this directory:

scripts/server/afx/effects/User

copy the grenade launcher from stock Torque3D:

art/datablocks/weapons/grenadeLauncher.cs

include it in datablockExec.cs and fix the path references to the art files!!!

Copy the shape folder:

art/shapes/weapons/grenadeLauncher

copy the 'ricochet' file:

art/shapes/particles/ricochet.png

then merge in scripts/server/weapons/grenadeLauncher.cs

remembering to include it in scriptExec.cs


and add the following script to the 'User' directory you created earlier.
The demo spellbook will automatically add it to the 'experimental' spellbank.

(gibby: had to edit the how-to on this one, should work now.
Stand on the hill overlooking the 'bivouac', cast in the middle of the crowd...)

//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// Da gibstah Presents:
//
// Hellfire & Brimstone
//
//  A Mash-Up of Acaster's 'CoD Minefield' and Pillar of Fire 
//  Click on the ground some distance from your player and watch...
//
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//

$AFX_VERSION = (isFunction(afxGetVersion)) ? afxGetVersion() : 1.02;
$MIN_REQUIRED_VERSION = 2.0;

// Test version requirements for this script
if ($AFX_VERSION < $MIN_REQUIRED_VERSION)
{
  error("AFX script " @ fileName($afxAutoloadScriptFile) @ " is not compatible with AFX versions older than " @ $MIN_REQUIRED_VERSION @ ".");
  return;
}

//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//

// Here we test if the script is being reloaded or if this is the
// first time the script has executed this mission.
//
$spell_reload = isObject(HellfireSpell);
if ($spell_reload)
{
  // mark datablocks so we can detect which are reloaded this script
  markDataBlocks();
  // reset data path from previously saved value
  %mySpellDataPath = HellfireSpell.spellDataPath;
}
else
{
  // set data path from default plus containing folder name //artafxeffects
  //%mySpellDataPath = $afxSpellDataPath @ "/" @ $afxAutoloadScriptFolder;
  %mySpellDataPath = $afxSpellDataPath @ "/Spellpack2";

  afxExecPrerequisite("clusters_of_fire.cs", $afxAutoloadScriptFolder);

}

//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//
// Marker Zode
//

datablock afxZodiacData(HnB_marker_Zode_CE)
{
  texture = "art/afx/effects/CoreTech/PHT/zodiacs/crop3_zode";
  radius = 2.0;
  startAngle = 0.0;
  rotationRate = 360.0;
  color = "1.0 0.0 0.0 0.5";
};
datablock afxEffectWrapperData(HnB_marker_Zode_EW)
{
  effect = HnB_marker_Zode_CE;
  constraint = "strike";
  lifetime = 1.5;
  fadeOutTime = 0.5;
};

//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//
// Script Event
//

datablock afxScriptEventData(HnB_LaunchHellfire_Script_CE)
{
  methodName = "LaunchHellfire";
};

datablock afxEffectWrapperData(HnB_LaunchHellfire_Script_EW)
{
  effect = HnB_LaunchHellfire_Script_CE;
  constraint = "strike";
  delay = 1.0;  
};

//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//
// Hellfire & Brimstone EFFECTRONs

datablock afxEffectronData(HellfireEffectron)
{
  echoPacketUsage = 20;
  duration = -1;
  numLoops = 1;
  execOnNewClients = true;
  
    // mine zodiacs //
  addEffect = HnB_marker_Zode_EW;
  addEffect = HnB_LaunchHellfire_Script_EW;
};

function HellfireEffectron::LaunchHellfire(%this, %strike, %cons, %xfm, %data)
{
   
   echo("c4HellfireEffectron::LaunchHellfire: "@%this.getName()@", strike: "@%strike@", %cons: "@%cons@" %xfm: "@%xfm@" data: "@%data);
   
   %numStrikes = getRandom(15,25);
   
   for (%i = 0; %i < %numStrikes; %i++)
   {
      
      //we start with an XYZ
	   %xfmX = firstWord(%xfm);
	   %xfmY = getWord(%xfm, 1);
	
	   //echo(%xfm);
	   //echo(%xfmX);
	   //echo(%xfmY);
	
	   //and extrapolate our max and min coordinates
	   %minX = %xfmX - 50;
	   %maxX = %xfmX + 50;
	
	   //echo(%minX);
	   //echo(%maxX);
	
	   %minY = %xfmY - 50;
	   %maxY = %xfmY + 50;
	
	   //echo(%maxY);
	   //echo(%minY);
	
	   %x = getRandom(%minX, %maxX);
	   %y = getRandom(%minY, %maxY);
	   //z will always be high above the terrain
	   //1024 should be enough to make sure it clears
	   //dependant on the actual xyz of the terrain and also it's highest point
	   %z = 1024;  
	   
	   //echo(%x SPC %y SPC %z);
	   %target = %x SPC %y SPC %z;
	   //echo(%target); 
	   
      %random = getRandom(500, 3000);
	   //and random pause before going back to prepareBombardment
	   //incase player is dead and we need a new controlObject to target
	   schedule(%random, 0, "strikeImpact", %target);
	   
	   echo("c4HellfireEffectron::LaunchHellfire: index: "@%i@", blast: "@%blast@", at target: "@%target);
   
      
   }
}

function strikeImpact(%start)
{
	//echo(%start);
	echo("c4Hellfire.cs->::strikeImpact start: "@%start);
   
	//look down and find something below up to 1500 units
	//you can probably get away with less but just to be sure
	%end = vectorSub(%start, "0 0 1500");
	//what we want to hit
	%mask = $TypeMasks::TerrainObjectType | $TypeMasks::StaticObjectType;
	
	
	%hit = ContainerRayCast(%start, %end, %mask);
	if(%hit == 0)
	{
		//echo("c2error: LINE OF SIGHT FOR BOMBARDMENT MISSED!");
		//ignore and bail!
		return;
	}
   
	//get the XYZ of the impact
	%xyz = getWords(%hit, 1, 3);

    //and spawn the stock grenadelauncher explosion
    %blast = new explosion()
	{
		dataBlock = "GrenadeLauncherExplosion";
		position = %xyz;
	};
	MissionCleanup.add(%blast);

   //add a pillar of fire...	
	%pillar_of_fire = startEffectron(PillarOfFireEffectron, %xyz, "anchor");
	
	//...and a cluster of fires...
   %exp_scale = getRandomF(0.8, 2.5);
   %n_fires = mCeil(((%exp_scale-0.8)/(2.5-0.8))*10);
   %radius = 6.0*%exp_scale;

  %cluster_fires = startClustersOfFire(%xfm, %n_fires, %radius);
	
	//add blast damage!
	radiusDamage(0, %xyz, 10, 25, "blastDamage", 2000);
	
	//and burn damage...
   %ring_radius = 10;

  // damage all players within the blast radius

  InitContainerRadiusSearch(%xyz, %ring_radius, $TypeMasks::PlayerObjectType | $TypeMasks::CorpseObjectType);
  while ((%in_obj = containerSearchNext()) != 0) 
  {
    %burn_obj = %in_obj;
    if (%burn_obj.uif_fire $= "")
    {
      %burn_obj.uif_fire = startEffectron(UpInFlamesEffectron, %burn_obj, "victim");
      %burn_obj.uif_fire._dur = getRandomF(9,11);
      %burn_obj.uif_fire.uif_victim = %burn_obj;
    }    
  }

	//and finally, slap on the stock decal at the impact site
	%decalObj = decalManagerAddDecal(%xyz, "0.0 0.0 1.0", 0, 1, "ScorchRXDecal", false);
}

//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//
// Hellfire & Brimstone SPELL
//

datablock afxMagicSpellData(HellfireSpell)
{
  //castingDur = 0;
};

datablock afxRPGMagicSpellData(HellfireSpell_RPG)
{
  spellName = "Hellfire & Brimstone";
  desc = "A Mash-Up of Acaster's 'CoD Minefield' and Pillar of Fire " @
         "Click on the ground some distance from your player and watch...n" @
         "n" @
         "<font:Arial Italic:14>original spell: <font:Arial:14>Matthew Durante and Jeff Faustn" @
         "<font:Arial Italic:14>original sound effects: <font:Arial:14>Matt Pacygan" @ 
         "<font:Arial Italic:14>Remixed by: <font:Arial:14>da Gibstah";  
  sourcePack = "Spell Pack 2";
  iconBitmap = "art/afx/effects/SpellPack2/PoF/icons/pof";
  manaCost = 10;
  castingDur = 0;
  target = "free";
};

function HellfireSpell::onLaunch(%this, %spell, %caster, %target, %missile)
{
  Parent::onLaunch(%this, %spell, %caster, %target, %missile);

  %anchor = %spell.freeTarget SPC getWords(%caster.getTransform(), 3);

  %effectron = startEffectron(HellfireEffectron, %anchor, "strike");
}

//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//

if ($spell_reload)
{
  // Removes then adds all reloaded datablocks
  touchDataBlocks();
}
else
{
  // save script filename and data path for reloads
  HellfireSpell.scriptFile = $afxAutoloadScriptFile;
  HellfireSpell.spellDataPath = %mySpellDataPath;
  if (isFunction(addDemoSpellbookSpell))
  {
    addDemoSpellbookSpell(HellfireSpell, HellfireSpell_RPG);
  }
}

//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//

#1
01/12/2013 (10:49 am)
@admin - May we make this a resource???
#2
01/12/2013 (11:19 am)
Would be nice with a video of the spell.. Not that I have AFX.. Just curious to see what it looks like :3
#3
01/12/2013 (11:39 am)
@Lukas: funny you should ask, I just uploaded a vid:

#4
01/14/2013 (4:44 am)
Moved to resources. Nice post Gibby!
#5
01/14/2013 (8:41 am)
@Michael - Thanks, you rock!