Gib Spawner code - Example/Opinions

Discussions about Coding and Scripting
Post Reply
MrLoathsome
Inhuman
Posts: 958
Joined: Wed Mar 31, 2010 9:02 pm
Personal rank: I am quite rank.
Location: MrLoathsome fell out of the world!

Gib Spawner code - Example/Opinions

Post by MrLoathsome »

Submitted for your approval, (or not...)

This is pretty much all the code, (except the boring config menu stuff), for the upcoming release of MoreGorePlus, which is a
rewrite of the old MoreGore mutator.

Posting this up both as sort of an example of how to do this sort of thing, and also to try and get any feedback from anybody who
takes the time to look at it and see's anything horribly wrong or out of place. (Seems to be working fine in testing so far....)

I think it is ready now, but figure I might as well see if I can get some input before I finalize things and try to write the readme.txt file
for it. Hope this isnt too much for posting in here. Just 2 classes. Tried to keep em as tight as possible.

Main mutator:

Code: Select all

//=========================================================================================
// MoreGore Plus Mutator by Mr.Loathsome.  Based on MoreGore2 by shiftre from Clan 404
//=========================================================================================
class MG expands Mutator;

var int goreLevel;
var float SpawnRate, GibRate;
var bool DigDugMode;
var rotator splatRotator;
var bool bInitialized, bDoSpawn;

function PostBeginPlay()
{
	if (bInitialized) return; else bInitialized = true;
	bDoSpawn = True;
	splatRotator.Pitch = 16384;
	Level.Game.RegisterDamageMutator(Self);
	
	goreLevel = class'MoreGore2ClientWindow'.Default.goreLevel;
	SpawnRate = class'MoreGore2ClientWindow'.Default.SpawnRate;
	GibRate = class'MoreGore2ClientWindow'.Default.GibRate;
	DigDugMode = class'MoreGore2ClientWindow'.Default.DigDugMode;
	Super.PostBeginPlay();
}

function Timer()
{
	bDoSpawn = True;
}

function ScoreKill(Pawn Killer, Pawn Other)
{
	local GibSpawn g;

	//Set up player explode on death if DigDugMode on
	if (DigDugMode)
	{
		Other.HidePlayer();
		Other.Fatness = 128;
		Other.Health = -100;
	}
	
	//check whether victim is at gib status
	if  (((bDoSpawn) && (ScriptedPawn(Other) != None)) || ((bDoSpawn) && ((Other.Health < -60) || ((Other.Health < -30) && (Other.FRand() < 0.6)))))
	{
		g = Spawn(class'GibSpawn', Other);
		if (g != None)
		{
			if ((ScriptedPawn(Other) != None) && (ScriptedPawn(Other).bGreenBlood))
			{
				g.SetLevel(goreLevel, Other.Location, True, GibRate);
			}
			else
			{
				g.SetLevel(goreLevel, Other.Location, False, GibRate);
			}
			Other.HidePlayer();
			SetTimer(SpawnRate, False);
			bDoSpawn = False;
		}
	}
	
	//Call next mutator down the line
	if ( NextMutator != None )
		NextMutator.ScoreKill(Killer, Other);
}

function MutatorTakeDamage( out int ActualDamage, Pawn Victim, Pawn InstigatedBy, out Vector HitLocation, 
						out Vector Momentum, name DamageType)
{
	local vector Mo;

	if ( NextDamageMutator != None)
		NextDamageMutator.MutatorTakeDamage( ActualDamage, Victim, InstigatedBy, HitLocation, Momentum, DamageType );	

	//Increase size of victim when hit if DigDugMode on
	if (DigDugMode) {
		if ((Victim.Fatness+ActualDamage)>255)
			Victim.Fatness = 255;
		else
			Victim.Fatness = Victim.Fatness+ActualDamage;
	}
	
	//Drop blood on hit & add more blood spray
//	if ((HitLocation.x != 0) && (HitLocation.y != 0) && (HitLocation.z != 0))
	if (HitLocation != vect(0,0,0))
	{
	Mo = Momentum;
	if ( Mo.Z > 0 )
		Mo.Z *= (0.9);
		if ((ScriptedPawn(Victim) != None) && (ScriptedPawn(Victim).bGreenBlood))
		{
			spawn( class'GreenBloodSpray', , , HitLocation, rotator(Mo));
		}
		else
		{
			spawn( class'BloodSpray', , , HitLocation, rotator(Mo));
			if (FRand() < 0.25)
				spawn( class'BloodSplat', , , Victim.Location, splatRotator);
		}
	}
}

defaultproperties
{
}
And the GibSpawner:

Code: Select all

class GibSpawn extends actor;

var int Ngibs;
var float GRate;
var bool bDoSpawn;
var vector cloc;
var pawn chunky;
var class<Pawn> pClass;

function SetLevel(int GLev, vector L, bool bGb, float GR)
{
	Ngibs = GLev;
	cloc = L;
	GRate = GR;
	if (bGb)
	{
		pClass = class'Unreali.Mercenary';
	}
	else
	{
		pClass = class'Unreali.Cow';
	}
	bDoSpawn = True;
	SetTimer(GRate, False);
}

function Timer()
{
	chunky = Spawn(pClass,,,cloc);
	if (chunky != None)
	{
		chunky.HidePlayer();
		chunky.health = -100;
		chunky.GotoState('Waiting');
	} else Destroy();
	bDoSpawn = True;
}

simulated function tick(float dt)
{
	if (bDoSpawn)
	{
		if (Ngibs <= 0)
		{
			if (chunky != None)
			{
				chunky.Destroy();
			}
			Destroy();
		}
		else
		{
			if (chunky != None)
			{
				chunky.SpawnGibbedCarcass();
				chunky.Destroy();
				Ngibs--;
				SetTimer(GRate, False);
				bDoSpawn = False;
			}
		}
	}
}

defaultproperties
{
	bHidden=True
}
Note: DigDug mode worked great in the original. Didn't touch the parts that deal with that in either ScoreKill or MutatorTakeDamage functions.
Green blood support, the GibSpawn class and the timers are the major changes with this.
Last edited by MrLoathsome on Thu Apr 28, 2011 1:41 am, edited 1 time in total.
blarg
JackGriffin
Godlike
Posts: 3774
Joined: Fri Jan 14, 2011 1:53 pm
Personal rank: -Retired-

Re: Gib Spawner code - Example/Opinions

Post by JackGriffin »

After working on the headshot for the sniper rifle I have to say that I was unaware at the complexity that a mutator like this requires. There is a lot going on and it's not easy to do. Well done sir.
So long, and thanks for all the fish
MrLoathsome
Inhuman
Posts: 958
Joined: Wed Mar 31, 2010 9:02 pm
Personal rank: I am quite rank.
Location: MrLoathsome fell out of the world!

Re: Gib Spawner code - Example/Opinions

Post by MrLoathsome »

Made a number of improvements to the above over the last few days.

Mutator download now available here: http://www.ut99.org/viewtopic.php?f=7&t=3210

Improvements in the code over the above are numerous. It now uses the correct carcasstype for
all scriptedpawns (monsters) and bots. For human players, I wasn't able to find a carcasstype set
so they just use a cow carcass.

Previous version was spawning an actual pawn, then hiding it and gibbing it and destroying it
every time the timer expired. And tick was calling the SpawnGibbedCarcass function.

Current version optimizes that quite a bit I think. "chunky" is now a carcass instead of a pawn and
only spawns once. I sort of integrated the SpawnGibbedCarcass function into the GibSpawn tick function.
Also reduced the number of bloodsprays and decals being generated to improve performance when this
is being used on a server. Still plenty of sprays, and the extra gibs produce so many decals I even considered
taking the extra decal out of MutatorTakeDamage.

Note: Use the DecalStay mutator or enable perm. decals at your own risk with this.... DecalStay might be ok, but use very low settings.


Below is the current version of the main code so you can compare it to the 1st draft:

Code: Select all

//=========================================================================================
// MoreGore Plus Mutator by Mr.Loathsome.  Based on MoreGore2 by shiftre from Clan 404
//=========================================================================================
class MG expands Mutator;

var int goreLevel;
var float SpawnRate, GibRate;
var bool DigDugMode;
var rotator splatRotator;
var bool bInitialized, bDoSpawn;

function PostBeginPlay()
{
	if (bInitialized) return; else bInitialized = true;
	bDoSpawn = True;
	splatRotator.Pitch = 16384;
	Level.Game.RegisterDamageMutator(Self);
	
	goreLevel = class'MoreGore2ClientWindow'.Default.goreLevel;
	SpawnRate = class'MoreGore2ClientWindow'.Default.SpawnRate;
	GibRate = class'MoreGore2ClientWindow'.Default.GibRate;
	DigDugMode = class'MoreGore2ClientWindow'.Default.DigDugMode;
	Super.PostBeginPlay();
}

function Timer()
{
	bDoSpawn = True;
}

function ScoreKill(Pawn Killer, Pawn Other)
{
	local GibSpawn g;

	//Set up player explode on death if DigDugMode on
	if (DigDugMode)
	{
		Other.HidePlayer();
		Other.Fatness = 128;
		Other.Health = -100;
	}
	
	//check whether victim is at gib status
	if ((bDoSpawn) && ((Other.Health < -40) || ((Other.Health < -10) && (FRand() < 0.5))))
	{
		g = Spawn(class'GibSpawn', Other);
		if (g != None)
		{
			Other.HidePlayer();
			if ((ScriptedPawn(Other) != None) && (ScriptedPawn(Other).CarcassType != None))
				{ g.SetLevel(goreLevel, (Other.Health-5), Other.Location, GibRate, ScriptedPawn(Other).CarcassType, True); }
			else {
			    if ((Bot(Other) != None) && (Bot(Other).CarcassType != None))
				{ g.SetLevel(goreLevel, Other.Health, Other.Location, GibRate, Bot(Other).CarcassType, False); }
			    else
				{ g.SetLevel(goreLevel, Other.Health, Other.Location, GibRate, class'CowCarcass', False); }
			     }
			SetTimer(SpawnRate, False);
			bDoSpawn = False;
		}
	}
	//Call next mutator down the line
	if ( NextMutator != None )
		NextMutator.ScoreKill(Killer, Other);
}

function MutatorTakeDamage( out int ActualDamage, Pawn Victim, Pawn InstigatedBy, out Vector HitLocation, 
						out Vector Momentum, name DamageType)
{
	local vector Mo;

	//Increase size of victim when hit if DigDugMode on
	if (DigDugMode) {
		if ((Victim.Fatness+ActualDamage)>255)
			Victim.Fatness = 255;
		else
			Victim.Fatness = Victim.Fatness+ActualDamage;
	}
	
	//Drop blood on hit & add more blood spray
	if (HitLocation != vect(0,0,0))
	{
		Mo = Momentum;
		if ( Mo.Z > 0 )
			Mo.Z *= (0.9);
		if ((ScriptedPawn(Victim) != None) && (ScriptedPawn(Victim).bGreenBlood))
		{
			if (FRand() < 0.25)
				spawn(class'GreenBloodSpray', , , HitLocation, rotator(Mo));
		}
		else
		{
			if (FRand() < 0.25)
				spawn( class'BloodSpray', , , HitLocation, rotator(Mo));
			if (FRand() < 0.10)
				spawn(class'BloodSplat', , , Victim.Location, splatRotator);
		}
	}
	if ( NextDamageMutator != None)
		NextDamageMutator.MutatorTakeDamage( ActualDamage, Victim, InstigatedBy, HitLocation, Momentum, DamageType );	
}

defaultproperties
{
}
And the new GibSpawn class:

Code: Select all

class GibSpawn extends actor;

var int Ngibs, PH;
var float GRate;
var bool bDoSpawn, bSp;
var vector cloc;
var class<carcass> pClass;

function SetLevel(int GLev, int PHealth, vector L, float GR, class<carcass> pC, bool bScrpawn)
{
	Ngibs = GLev;
	PH = PHealth;
	cloc = L;
	GRate = GR;
	pClass = pC;
	bSp = bScrpawn;
	bDoSpawn = True;
	SetTimer(GRate, False);
}

function Timer()
{
	bDoSpawn = True;
}

function tick(float dt)
{
	local carcass chunky;

	if (bDoSpawn)
	{
		if (chunky == None)
		{
			chunky = Spawn(pClass,,,cloc);
			if (bSp) chunky.Initfor(Self);
		}
		chunky.ChunkUp(-1 * PH);
		Ngibs--;
		SetTimer(GRate, False);
		bDoSpawn = False;		
		if (Ngibs <= 0)
		{
			if (chunky != None)
			{
				chunky.Destroy();
			}
			Destroy();
		}
	}
}

defaultproperties
{
	bHidden=True
}
blarg
Post Reply