I recently got an inquiry from a person who wanted to know how to modify my previous mutator to not cause damage. Following is a description of how to do this. This also updates my mutator mod info for the UnrealEd 2.0 tool.
First you need to have Unreal Tournament and UnrealEd installed. Fire up UnrealED 2.0 and fire up the Actor Class browser by selecting View->Actor Class Browser:

Once in the actor class browser export the source source code by selecting File->Export All Scripts:

This will dump all of Unreal Tournament's classes into the directory (Botpack) where Unreal Tournament is installed. You only need to do this once*. I strongly encourage you to browse the scripts in these directories. They're very instructional. The rest of the steps are the sames as for Boom.
*Actually it's a good idea to do this each time you patch Unreal Tournament to pick up the latest fixes.Boom is a specialization of two classes; Boom (from the last exercise) and Shockwave (from UT). The Showckwave class does not have a damage attribute so we need to subclass it and slightly modify its logic. Boom needs to be modified to call the new shockwave class. The changes will be made in such a manner so that the original Boom mod is left in the game also.
All locations are relative to the UT game directory.
<gamedir>\MyPackages\Classes\ShockwaveNoDamage.uc (new)
<gamedir>\MyPackages\Classes\BoomNoDamage.uc (new)
<gamedir>\System\MyPackages.int (Modified)
<gamedir>\System\UnrealTournament.ini (Modified)
This is a basically a stripped down version of <gamedir>\Botpack\Classes\Shockwave.uc with just the timer method remaining:
class ShockWaveNoDamage extends ShockWave;
simulated function Timer()
{
local actor Victims;
local float damageScale, dist, MoScale;
local vector dir;
ShockSize = 13 * (Default.LifeSpan - LifeSpan) + 3.5/(LifeSpan/Default.LifeSpan+0.05);
if ( Level.NetMode != NM_DedicatedServer )
{
if (ICount==4) spawn(class'WarExplosion2',,,Location);
ICount++;
if ( Level.NetMode == NM_Client )
{
foreach VisibleCollidingActors( class 'Actor', Victims, ShockSize*29, Location )
{
if ( Victims.Role == ROLE_Authority )
{
dir = Victims.Location - Location;
dist = FMax(1,VSize(dir));
dir = dir/dist +vect(0,0,0.3);
if ( (dist> OldShockDistance) || (dir dot Victims.Velocity <= 0))
{
MoScale = FMax(0, 1100 - 1.1 * Dist);
Victims.Velocity = Victims.Velocity + dir * (MoScale + 20);
// Victims.TakeDamage
// (
// MoScale,
// Instigator,
// Victims.Location - 0.5 * (Victims.CollisionHeight + Victims.CollisionRadius) * dir,
// (1000 * dir),
// 'RedeemerDeath'
// );
}
}
}
return;
}
}
foreach VisibleCollidingActors( class 'Actor', Victims, ShockSize*29, Location )
{
dir = Victims.Location - Location;
dist = FMax(1,VSize(dir));
dir = dir/dist + vect(0,0,0.3);
if (dist> OldShockDistance || (dir dot Victims.Velocity < 0))
{
MoScale = FMax(0, 1100 - 1.1 * Dist);
if ( Victims.bIsPawn )
Pawn(Victims).AddVelocity(dir * (MoScale + 20));
else
Victims.Velocity = Victims.Velocity + dir * (MoScale + 20);
// Victims.TakeDamage
// (
// MoScale,
// Instigator,
// Victims.Location - 0.5 * (Victims.CollisionHeight + Victims.CollisionRadius) * dir,
// (1000 * dir),
// 'RedeemerDeath'
// );
}
}
OldShockDistance = ShockSize*29;
}
Note I have commented out the damage routines but have left in the physics code so the shockwave still throws people and bots around.
This is a the same as <gamedir>\MyPackages\Classes\Boom.uc Except that the class has been renamed and the spawn command spawns ShockwaveNoDamage instead of Shockwave:
class BoomNoDamage expands Mutator;
var bool Initialized;
function PostBeginPlay()
{
//
// Install only once
//
if (Initialized)
return;
Initialized = True;
Level.Game.RegisterDamageMutator( Self );
}
function MutatorTakeDamage(
out int ActualDamage,
Pawn Victim,
Pawn InstigatedBy,
out Vector HitLocation,
out Vector Momentum,
name DamageType
)
{
local Shockwave explosion;
if (Victim.IsA('Bot') || Victim.IsA('PlayerPawn'))
{
if (Victim.Health <= ActualDamage)
{
explosion = Spawn(class 'ShockwaveNoDamage',,,Victim.Location);
explosion.Instigator = Victim;
}
}
//
// Pass on the event to the next handler
//
if ( NextDamageMutator != None )
NextDamageMutator.MutatorTakeDamage( ActualDamage, Victim, InstigatedBy, HitLocation, Momentum, DamageType );
}
[Public] Object=(Name=MyPackages.Boom,Class=Class,MetaClass=Engine.Mutator,Description="Boom: When person dies they explode.") Object=(Name=MyPackages.BoomNoDamage,Class=Class,MetaClass=Engine.Mutator,Description="Boom (no Damage): When person dies they explode.") Object=(Name=MyPackages.ShockWaveNoDamage,Class=Class,MetaClass=Engine.Effect,Description="Redeemer shockwave but without damage.")
Edit System/unrealtournament.ini. Find the selection with lines like EditPackages=
EditPackages=MyPackages
This should be there from the previous mod but just to
make certain...
Create a DOS (Command) Window. cd to your Unreal Tournament System directory. Type:
del mypackages.u & ucc makeand you should see something like:
C:\Games\UnrealTournament\System>del MyPackages.u & ucc make all --------------------Core-------------------- --------------------Engine-------------------- --------------------Editor-------------------- --------------------UWindow-------------------- --------------------Fire-------------------- --------------------IpDrv-------------------- --------------------UWeb-------------------- --------------------UBrowser-------------------- --------------------UnrealShare-------------------- --------------------UnrealI-------------------- --------------------UMenu-------------------- --------------------IpServer-------------------- --------------------Botpack-------------------- --------------------UTServerAdmin-------------------- --------------------UTMenu-------------------- --------------------UTBrowser-------------------- --------------------MyPackages-------------------- Analyzing... Parsing Boom Parsing BoomNoDamage Parsing ShockWaveNoDamage Compiling Boom Compiling BoomNoDamage Compiling ShockWaveNoDamage Success - 0 error(s), 0 warnings
The delete command is to make certain that MyPackage.int builds. For some reason ucc does not seem to do a date check all of the time to see what needs to be built.
Fire up Unreal Tournament. Pick a practice session, a map, the mutator "Boom (no damage): When person dies they explode.", several bots, and press "Start". Kill someone and watch them go boom!
This zip file contains all of the code except for the modification to unrealtournament.ini.