Is it hard to script a mutator that gives a spawnkiller a warning after 5 or 10 ( adjustable amount) spawnkills and then after another amount of spawnkills ( adjustable ) kills the spawnkiller with the "explode into gibs style"
Ive seen the message on a server saying " .... is a spawnkilling lamer"
It would think its a cool idea to have a mutator that also uses that message but kills the spawnkiller after a certain amount of spawnkills. And have the gibs everywhere. Also i could expand on it with different variety's for instance give spawnkiller bright flashing color overlay for a certain amount of time, make him like the fatboy mutator, mske him frozen like freeze-tag or just kick him of server.
I have no idea where to start, i know how to set up my folders and use uccmake but that about it.
Wich script should i start with?
Let Spawnkiller Explode
-
- Adept
- Posts: 300
- Joined: Mon Oct 02, 2017 9:39 am
Let Spawnkiller Explode
Character tools and tutorials https://drive.google.com/drive/folders/ ... fMEQ2w212Z
-
- Adept
- Posts: 376
- Joined: Thu Mar 25, 2010 6:00 pm
- Personal rank: UMS R&D CEO
Re: Let Spawnkiller Explode
A much more simpler solution would be to give players on spawning a temporary shieldbelt. Unlike other armors, shieldbelts eat all damage first before health starts dropping, so a 99999-value shieldbelt that disappears after a few seconds would get the job done.
As for telefragging, some coop servers on Newbies have, as I have observed, a mechanic which allows players to spawn beside the existing spawnpoints if area is taken. At least that's what I ASSUME is happening since I've never been telefragged or haven't telefragged anyone in coop sessions there. Translating this mechanic to UT gametypes should get the job done, and even prevent translocator telefragging if we'd so desire.
As for telefragging, some coop servers on Newbies have, as I have observed, a mechanic which allows players to spawn beside the existing spawnpoints if area is taken. At least that's what I ASSUME is happening since I've never been telefragged or haven't telefragged anyone in coop sessions there. Translating this mechanic to UT gametypes should get the job done, and even prevent translocator telefragging if we'd so desire.

I am the Unreal archivist and historian. If you have something from the past of Unreal that I don't have, do tell.
~formerly Delacroix
-
- Adept
- Posts: 300
- Joined: Mon Oct 02, 2017 9:39 am
Re: Let Spawnkiller Explode
thats not funny enough.TigerTheGreat wrote: ↑Sat Apr 26, 2025 2:08 pm A much more simpler solution would be to give players on spawning a temporary shieldbelt. Unlike other armors, shieldbelts eat all damage first before health starts dropping, so a 99999-value shieldbelt that disappears after a few seconds would get the job done.
As for telefragging, some coop servers on Newbies have, as I have observed, a mechanic which allows players to spawn beside the existing spawnpoints if area is taken. At least that's what I ASSUME is happening since I've never been telefragged or haven't telefragged anyone in coop sessions there. Translating this mechanic to UT gametypes should get the job done, and even prevent translocator telefragging if we'd so desire.
i tried with chatgpt today but its useless. giving me wrong code everytime. programmers looking at this probably laughing their ass of how crappy it is.
example
Code: Select all
class SpawnKillPunisher extends Mutator;
var config int MaxSpawnKills;
var config float SpawnKillTime;
struct SpawnKillTracker
{
var Pawn P;
var float LastSpawnTime;
var int SpawnKillCount;
};
var array<SpawnKillTracker> Trackers;
function PostBeginPlay()
{
Super.PostBeginPlay();
MaxSpawnKills = 3;
SpawnKillTime = 5.0;
// Show message that Mutator is active
local PlayerPawn P;
foreach AllActors(class'PlayerPawn', P)
{
P.ClientMessage("[SpawnKillPunisher] Mutator Loaded!");
}
}
function ModifyPlayer(Pawn Other)
{
local int i;
Super.ModifyPlayer(Other);
if (Other == None)
return;
// Check if already tracked
for (i = 0; i < Trackers.Length; i++)
{
if (Trackers[i].P == Other)
return;
}
// Add new tracker
Trackers.Length = Trackers.Length + 1;
Trackers[Trackers.Length-1].P = Other;
Trackers[Trackers.Length-1].LastSpawnTime = Level.TimeSeconds;
Trackers[Trackers.Length-1].SpawnKillCount = 0;
if (Other.IsA('PlayerPawn'))
PlayerPawn(Other).ClientMessage("[SpawnKillPunisher] You are now being tracked!");
}
function ScoreKill(Pawn Killer, Pawn Other)
{
local int i;
local float TimeSinceSpawn;
Super.ScoreKill(Killer, Other);
if (Killer == None || Other == None)
return;
for (i = 0; i < Trackers.Length; i++)
{
if (Trackers[i].P == Other)
{
TimeSinceSpawn = Level.TimeSeconds - Trackers[i].LastSpawnTime;
if (TimeSinceSpawn <= SpawnKillTime)
{
// Find killer tracker
for (i = 0; i < Trackers.Length; i++)
{
if (Trackers[i].P == Killer)
{
Trackers[i].SpawnKillCount++;
if (Killer.IsA('PlayerPawn'))
{
PlayerPawn(Killer).ClientMessage("[SpawnKillPunisher] Spawnkill detected! ("$Trackers[i].SpawnKillCount$"/"$MaxSpawnKills$")");
}
if (Trackers[i].SpawnKillCount >= MaxSpawnKills)
{
if (Killer.IsA('PlayerPawn'))
PlayerPawn(Killer).ClientMessage("[SpawnKillPunisher] You have been punished for spawnkilling!");
Killer.TakeDamage(9999, Killer, Killer.Location, vect(0,0,0), 'FlakShell');
Trackers[i].SpawnKillCount = 0;
}
break;
}
}
}
break;
}
}
// Update victim's spawn time
for (i = 0; i < Trackers.Length; i++)
{
if (Trackers[i].P == Other)
{
Trackers[i].LastSpawnTime = Level.TimeSeconds;
break;
}
}
}
defaultproperties
{
}
i tried starting a match with lots of bots in a modified map where spawnpoints are close together and after starting the match i used "loaded" and "fly" to hover over the enemy base and shoot rockets but none of the 20 different version from chatgpt worked, atleast i geuss its just disfunctional code, i remove the old .u file everytime before recompiling, not sure what else i can do wrong to not make it work.
-
-
Character tools and tutorials https://drive.google.com/drive/folders/ ... fMEQ2w212Z
-
- Godlike
- Posts: 3093
- Joined: Fri Sep 25, 2015 9:01 pm
- Location: moved without proper hashing
Re: Let Spawnkiller Explode
The code is close to what my idea was: You have to track spawned players for a while - maybe some seconds - and if they are killed within this interval (and eventually within a certain range around the spawn point), it is counted as a spawn kill. Then you can do what you want with the killer: ban, freeze, decrease health, kill, …
But the code looks like for a newer version of unreal; UT has no dynamic arrays nor things like
Auto merged new post submitted 28 minutes later
I rewrote the code for UT. Untested, but at least it compiles.
Todo: add a cleanup for outdated SpawnKillTracker
But the code looks like for a newer version of unreal; UT has no dynamic arrays nor things like
Trackers.Length
. Auto merged new post submitted 28 minutes later
I rewrote the code for UT. Untested, but at least it compiles.
Todo: add a cleanup for outdated SpawnKillTracker
Code: Select all
class SpawnKillTracker expands Info;
var Pawn P;
var float LastSpawnTime;
var int SpawnKillCount;
Code: Select all
class SpawnKillPunisher expands Mutator;
var config int MaxSpawnKills;
var config float SpawnKillTime;
function bool FindTrackerFor(Pawn P, out SpawnKillTracker SKT) {
foreach AllActors(class'SpawnKillTracker', SKT, P.Name)
break;
return SKT != None;
}
function ModifyPlayer(Pawn Other) {
local SpawnKillTracker Tracker;
Super.ModifyPlayer(Other);
if (Other == None) return;
// Check if already tracked
if (FindTrackerFor(Other, Tracker)) return;
// Add new tracker
Tracker = Spawn(class'SpawnKillTracker');
if (Tracker != None)
{
Tracker.Tag = Other.Name;
Tracker.P = Other;
Tracker.LastSpawnTime = Level.TimeSeconds;
Tracker.SpawnKillCount = 0;
}
else
warn("Could not spawn a SpawnKillTracker");
if (Other.IsA('PlayerPawn'))
PlayerPawn(Other).ClientMessage("[SpawnKillPunisher] You are now being tracked!");
}
function ScoreKill(Pawn Killer, Pawn Other) {
local float TimeSinceSpawn;
local SpawnKillTracker AVictim, Akiller;
Super.ScoreKill(Killer, Other);
if (Killer == None || Other == None) return;
if (FindTrackerFor(Other, AVictim))
{
TimeSinceSpawn = Level.TimeSeconds - AVictim.LastSpawnTime;
if (TimeSinceSpawn <= SpawnKillTime)
{
// Find killer's tracker
if (FindTrackerFor(Other, AKiller))
{
AKiller.SpawnKillCount++;
if (Killer.IsA('PlayerPawn')) PlayerPawn(Killer).ClientMessage("[SpawnKillPunisher] Spawnkill detected! (" $ AKiller.SpawnKillCount $ "/" $ MaxSpawnKills$")");
if (AKiller.SpawnKillCount >= MaxSpawnKills)
{
if (Killer.IsA('PlayerPawn')) PlayerPawn(Killer).ClientMessage("[SpawnKillPunisher] You have been punished for spawnkilling!");
// do punishment here:
Killer.TakeDamage(9999, Killer, Killer.Location, vect(0,0,0), 'FlakShell');
// reset killer's AKiller:
AKiller.SpawnKillCount = 0;
}
}
}
}
// Update victim's spawn time
AVictim.LastSpawnTime = Level.TimeSeconds;
}
defaultproperties {
MaxSpawnKills=3
SpawnKillTime=5.0
}
"If Origin not in center it be not in center." --Buggie
-
- Adept
- Posts: 300
- Joined: Mon Oct 02, 2017 9:39 am
Re: Let Spawnkiller Explode
Barbie wrote: ↑Sun Apr 27, 2025 1:14 am The code is close to what my idea was: You have to track spawned players for a while - maybe some seconds - and if they are killed within this interval (and eventually within a certain range around the spawn point), it is counted as a spawn kill. Then you can do what you want with the killer: ban, freeze, decrease health, kill, …
But the code looks like for a newer version of unreal; UT has no dynamic arrays nor things likeTrackers.Length
.
Auto merged new post submitted 28 minutes later
I rewrote the code for UT. Untested, but at least it compiles.
Todo: add a cleanup for outdated SpawnKillTracker
Code: Select all
class SpawnKillTracker expands Info; var Pawn P; var float LastSpawnTime; var int SpawnKillCount;
Code: Select all
class SpawnKillPunisher expands Mutator; var config int MaxSpawnKills; var config float SpawnKillTime; function bool FindTrackerFor(Pawn P, out SpawnKillTracker SKT) { foreach AllActors(class'SpawnKillTracker', SKT, P.Name) break; return SKT != None; } function ModifyPlayer(Pawn Other) { local SpawnKillTracker Tracker; Super.ModifyPlayer(Other); if (Other == None) return; // Check if already tracked if (FindTrackerFor(Other, Tracker)) return; // Add new tracker Tracker = Spawn(class'SpawnKillTracker'); if (Tracker != None) { Tracker.Tag = Other.Name; Tracker.P = Other; Tracker.LastSpawnTime = Level.TimeSeconds; Tracker.SpawnKillCount = 0; } else warn("Could not spawn a SpawnKillTracker"); if (Other.IsA('PlayerPawn')) PlayerPawn(Other).ClientMessage("[SpawnKillPunisher] You are now being tracked!"); } function ScoreKill(Pawn Killer, Pawn Other) { local float TimeSinceSpawn; local SpawnKillTracker AVictim, Akiller; Super.ScoreKill(Killer, Other); if (Killer == None || Other == None) return; if (FindTrackerFor(Other, AVictim)) { TimeSinceSpawn = Level.TimeSeconds - AVictim.LastSpawnTime; if (TimeSinceSpawn <= SpawnKillTime) { // Find killer's tracker if (FindTrackerFor(Other, AKiller)) { AKiller.SpawnKillCount++; if (Killer.IsA('PlayerPawn')) PlayerPawn(Killer).ClientMessage("[SpawnKillPunisher] Spawnkill detected! (" $ AKiller.SpawnKillCount $ "/" $ MaxSpawnKills$")"); if (AKiller.SpawnKillCount >= MaxSpawnKills) { if (Killer.IsA('PlayerPawn')) PlayerPawn(Killer).ClientMessage("[SpawnKillPunisher] You have been punished for spawnkilling!"); // do punishment here: Killer.TakeDamage(9999, Killer, Killer.Location, vect(0,0,0), 'FlakShell'); // reset killer's AKiller: AKiller.SpawnKillCount = 0; } } } } // Update victim's spawn time AVictim.LastSpawnTime = Level.TimeSeconds; } defaultproperties { MaxSpawnKills=3 SpawnKillTime=5.0 }
Thank you, its not really working yet. i had a alot of trial and error this morning with using Chatgpt ( each time it says; here is the real working version and i fails again

Also because i had some problem when compiling and told me no file could be found and now i have duplicate source files in seperate folders but it does not seem to care.
This is what i have now; spawnkillmanager is in its own folder but also in spawnkillpunisher folder, spawnkillpunisher is in its own folder only ( no duplicate) together with the spawnkillpunisher.int and the spawnkillmanger.uc for now because im to afraid to delete one it right now while its working like its now at the moment. under editpackages i have both spawnkillmanager and spawnkillpunisher.
so i just needed to share my tiny progress this morning before going on family visit.
Code: Select all
// SpawnKillManager.uc
class SpawnKillManager expands Actor;
var config int MaxSpawnKills; // How many spawnkills allowed before punishment
var config float SpawnKillTime; // Time window to detect spawnkill (seconds)
struct TrackerData
{
var Pawn P; // The player
var float LastSpawnTime; // When they spawned
var int SpawnKillCount; // How many spawnkills
};
var TrackerData Trackers[32]; // Static array (no dynamic arrays in UT99)
var int TrackerCount;
event PostBeginPlay()
{
SetTimer(1.0, true);
}
function Timer()
{
local Pawn P;
local int i;
// Look for new players to track
foreach AllActors(class'Pawn', P)
{
if (!IsTracked(P))
{
AddTracker(P);
if (P.IsA('PlayerPawn'))
PlayerPawn(P).ClientMessage("[SpawnKillPunisher] You are now being tracked!");
}
}
// Cleanup: Remove dead players
for (i = 0; i < TrackerCount; i++)
{
if (Trackers[i].P == None || Trackers[i].P.bDeleteMe || Trackers[i].P.Health <= 0)
{
RemoveTracker(i);
i--; // Shifted, recheck this index
}
}
}
function bool IsTracked(Pawn P)
{
local int i;
for (i = 0; i < TrackerCount; i++)
{
if (Trackers[i].P == P)
return true;
}
return false;
}
function AddTracker(Pawn P)
{
if (TrackerCount >= 32)
return;
Trackers[TrackerCount].P = P;
Trackers[TrackerCount].LastSpawnTime = Level.TimeSeconds;
Trackers[TrackerCount].SpawnKillCount = 0;
TrackerCount++;
}
function RemoveTracker(int index)
{
local int i;
for (i = index; i < TrackerCount-1; i++)
Trackers[i] = Trackers[i+1];
TrackerCount--;
}
function NotifyKilled(Pawn Killer, Pawn Victim)
{
local int i;
local float TimeSinceSpawn;
if (Killer == None || Victim == None)
return;
// Find Victim tracker
for (i = 0; i < TrackerCount; i++)
{
if (Trackers[i].P == Victim)
{
TimeSinceSpawn = Level.TimeSeconds - Trackers[i].LastSpawnTime;
if (TimeSinceSpawn <= SpawnKillTime)
{
Punish(Killer);
}
break;
}
}
}
function Punish(Pawn Killer)
{
local int i;
// Find Killer tracker
for (i = 0; i < TrackerCount; i++)
{
if (Trackers[i].P == Killer)
{
Trackers[i].SpawnKillCount++;
if (Killer.IsA('PlayerPawn'))
PlayerPawn(Killer).ClientMessage("[SpawnKillPunisher] Spawnkill detected! (" $ Trackers[i].SpawnKillCount $ "/" $ MaxSpawnKills $ ")");
if (Trackers[i].SpawnKillCount >= MaxSpawnKills)
{
if (Killer.IsA('PlayerPawn'))
PlayerPawn(Killer).ClientMessage("[SpawnKillPunisher] You have been punished for spawnkilling!");
Killer.TakeDamage(9999, Killer, Killer.Location, vect(0,0,0), 'SpawnKillPunish');
Trackers[i].SpawnKillCount = 0;
}
break;
}
}
}
defaultproperties
{
MaxSpawnKills=3
SpawnKillTime=20.0
}
Code: Select all
// SpawnKillPunisher.uc
class SpawnKillPunisher expands Mutator;
var SpawnKillManager Manager;
function PostBeginPlay()
{
Super.PostBeginPlay();
Manager = Spawn(class'SpawnKillManager');
}
function ScoreKill(Pawn Killer, Pawn Other)
{
Super.ScoreKill(Killer, Other);
if (Manager != None)
Manager.NotifyKilled(Killer, Other);
}
defaultproperties
{
}
Character tools and tutorials https://drive.google.com/drive/folders/ ... fMEQ2w212Z
-
- Godlike
- Posts: 3093
- Joined: Fri Sep 25, 2015 9:01 pm
- Location: moved without proper hashing
Re: Let Spawnkiller Explode
Anything of interest in the log file?
"If Origin not in center it be not in center." --Buggie
-
- Adept
- Posts: 300
- Joined: Mon Oct 02, 2017 9:39 am
Re: Let Spawnkiller Explode
No nothing, i think this version is now functioning with help of Chatgpt , changed spawnkillmanager into this
Code: Select all
// SpawnKillManager.uc
class SpawnKillManager expands Actor;
var config int MaxSpawnKills; // How many spawnkills allowed before punishment
var config float SpawnKillTime; // Time window to detect spawnkill (seconds)
struct TrackerData
{
var Pawn P; // The player
var float LastSpawnTime; // When they spawned
var int SpawnKillCount; // How many spawnkills
};
var TrackerData Trackers[32]; // Static array (no dynamic arrays in UT99)
var int TrackerCount;
event PostBeginPlay()
{
SetTimer(1.0, true);
}
function Timer()
{
local Pawn P;
local int i;
// Look for new players to track
foreach AllActors(class'Pawn', P)
{
if (!IsTracked(P))
{
AddTracker(P);
if (P.IsA('PlayerPawn'))
PlayerPawn(P).ClientMessage("[SpawnKillPunisher] You are now being tracked!");
}
}
// Cleanup: Remove dead players
for (i = 0; i < TrackerCount; i++)
{
if (Trackers[i].P == None || Trackers[i].P.bDeleteMe || Trackers[i].P.Health <= 0)
{
RemoveTracker(i);
i--; // Shifted, recheck this index
}
}
}
function bool IsTracked(Pawn P)
{
local int i;
for (i = 0; i < TrackerCount; i++)
{
if (Trackers[i].P == P)
return true;
}
return false;
}
function AddTracker(Pawn P)
{
if (TrackerCount >= 32)
return;
Trackers[TrackerCount].P = P;
Trackers[TrackerCount].LastSpawnTime = Level.TimeSeconds;
Trackers[TrackerCount].SpawnKillCount = 0;
TrackerCount++;
}
function RemoveTracker(int index)
{
local int i;
for (i = index; i < TrackerCount-1; i++)
Trackers[i] = Trackers[i+1];
TrackerCount--;
}
function NotifyKilled(Pawn Killer, Pawn Victim)
{
local int i;
local float TimeSinceSpawn;
if (Killer == None || Victim == None)
return;
// Find Victim tracker
for (i = 0; i < TrackerCount; i++)
{
if (Trackers[i].P == Victim)
{
TimeSinceSpawn = Level.TimeSeconds - Trackers[i].LastSpawnTime;
if (TimeSinceSpawn <= SpawnKillTime)
{
Punish(Killer);
}
break;
}
}
}
function Punish(Pawn Killer)
{
local int i;
if (Killer == None || Killer.bDeleteMe || Killer.Health <= 0)
return; // Already dead or being destroyed, skip punishment!
for (i = 0; i < TrackerCount; i++)
{
if (Trackers[i].P == Killer)
{
Trackers[i].SpawnKillCount++;
if (Killer.IsA('PlayerPawn'))
PlayerPawn(Killer).ClientMessage("[SpawnKillPunisher] Spawnkill detected! (" $ Trackers[i].SpawnKillCount $ "/" $ MaxSpawnKills $ ")");
if (Trackers[i].SpawnKillCount >= MaxSpawnKills)
{
if (Killer.IsA('PlayerPawn'))
PlayerPawn(Killer).ClientMessage("[SpawnKillPunisher] You have been punished for spawnkilling!");
// Avoid infinite recursion:
Killer.Health = -10000;
Killer.Died(None, 'SpawnKillPunish', Killer.Location);
Trackers[i].SpawnKillCount = 0;
}
break;
}
}
}
defaultproperties
{
MaxSpawnKills=3
SpawnKillTime=20.0
}
i hope to get rid of that and build nice version with warnings on screen instead of the console to make violations more visible and maybe add other option like gibs, freeze, bright colors if thats even possible. not sure, any suggestions?
someone wants to test it?
-
-
You do not have the required permissions to view the files attached to this post.
Character tools and tutorials https://drive.google.com/drive/folders/ ... fMEQ2w212Z
-
- Godlike
- Posts: 3093
- Joined: Fri Sep 25, 2015 9:01 pm
- Location: moved without proper hashing
Re: Let Spawnkiller Explode
Just a hint for better efficiency: Instead of checking the Trackers mostly useless in every timer period (aka "polling"), I'd check them only when needed: on Player join and logoff (aka "event driven").
"If Origin not in center it be not in center." --Buggie