UE1 - UT Keeping Weapons Despite Death

  • Two Factor Authentication is now available on BeyondUnreal Forums. To configure it, visit your Profile and look for the "Two Step Verification" option on the left side. We can send codes via email (may be slower) or you can set up any TOTP Authenticator app on your phone (Authy, Google Authenticator, etc) to deliver codes. It is highly recommended that you configure this to keep your account safe.

Zur

surrealistic mad cow
Jul 8, 2002
11,708
8
38
48
It may help to look at the source of monsterhunt seeing the gametype usually relays calls to these mutator functions.
 

gopostal

Active Member
Jan 19, 2006
848
47
28
This is from the monsterhunt.uc:

Code:
function ScoreKill(pawn Killer, pawn Other)
{
	local ScriptedPawn S;

	if ( (Killer == None) || (Killer == Other) || !Other.bIsPlayer 
		|| (Killer.PlayerReplicationInfo.Team != Other.PlayerReplicationInfo.Team) )
		Super.ScoreKill(Killer, Other);

	MonstersTotal = 0;

	foreach AllActors(class'ScriptedPawn', S)
	{
		if (S.Health >= 1)
			MonstersTotal ++;
		if (S.Shadow == None)
			SetPawnDifficulty(MonsterSkill, S);
	}

	MonsterReplicationInfo(GameReplicationInfo).Monsters = MonstersTotal;

	if (Other.bIsPlayer && MonsterReplicationInfo(GameReplicationInfo).bUseLives)
		Other.PlayerReplicationInfo.Deaths -= 1;

 	if(!Other.IsA('ScriptedPawn')) return;

	if(Killer!=None)
 	{
    		BroadcastMessage(Killer.GetHumanName()@"killed"$Other.GetHumanName());
 	}

// =========================================================================
// Score depending on which monster type the player kills

	if ( (Killer.bIsPlayer) && ( (Other.IsA('Titan')) || (Other.IsA('Queen')) || (Other.IsA('WarLord')) ) )
		Killer.PlayerReplicationInfo.Score += 4;
	if ( (Killer.bIsPlayer) && ( (Other.IsA('GiantGasBag')) || (Other.IsA('GiantManta')) ) )
		Killer.PlayerReplicationInfo.Score += 3;
	if ( (Killer.bIsPlayer) && ( (Other.IsA('SkaarjWarrior')) || (Other.IsA('MercenaryElite')) || (Other.IsA('Brute')) ) )
		Killer.PlayerReplicationInfo.Score += 2;
	if ( (Killer.bIsPlayer) && ( (Other.IsA('SkaarjTrooper')) || ( (Other.IsA('Mercenary')) && (!Other.IsA('MercenaryElite')) ) || (Other.IsA('Krall')) || (Other.IsA('Slith')) || ( (Other.IsA('GasBag')) && (!Other.IsA('GiantGasBag')) ) ) )
		Killer.PlayerReplicationInfo.Score += 1;

	// Lose points for killing innocent creatures. Shame ;-)
	if ( (Killer.bIsPlayer) && ( (Other.IsA('Nali')) || (Other.IsA('Cow')) || (Other.IsA('NaliRabbit')) ) )
		Killer.PlayerReplicationInfo.Score -= 6;

	// Get 10 extra points for killing the boss!!

	if (Other.IsA('ScriptedPawn'))
		S = ScriptedPawn(Other);
	if ( (Killer.bIsPlayer) && ( S.bIsBoss ) )
		Killer.PlayerReplicationInfo.Score += 9;
}

function AddToTeam( int num, Pawn Other )
{
	local teaminfo aTeam;
	local Pawn P;
	local bool bSuccess;
	local string SkinName, FaceName;

	if ( Other != None )
	{
		aTeam = Teams[0];
		aTeam.Size++;
		Other.PlayerReplicationInfo.Team = 0;
		Other.PlayerReplicationInfo.TeamName = aTeam.TeamName;
		bSuccess = false;
		if ( Other.IsA('PlayerPawn') )
		{
			Other.PlayerReplicationInfo.TeamID = 0;
			PlayerPawn(Other).ClientChangeTeam(Other.PlayerReplicationInfo.Team);
		}
		else
			Other.PlayerReplicationInfo.TeamID = 1;

		while ( !bSuccess )
		{
			bSuccess = true;
			for ( P=Level.PawnList; P!=None; P=P.nextPawn )
				if ( P.bIsPlayer && (P != Other) 
					&& (P.PlayerReplicationInfo.Team == Other.PlayerReplicationInfo.Team) 
					&& (P.PlayerReplicationInfo.TeamId == Other.PlayerReplicationInfo.TeamId) )
			{	
				Other.PlayerReplicationInfo.TeamID++;
				bSuccess = False;
			}
		}

		if (MonsterReplicationInfo(GameReplicationInfo).bUseLives)
			Other.PlayerReplicationInfo.Deaths = MonsterReplicationInfo(GameReplicationInfo).Lives;

		if (MonsterReplicationInfo(GameReplicationInfo).bUseTeamSkins)
		{
			Other.static.GetMultiSkin(Other, SkinName, FaceName);
			Other.static.SetMultiSkin(Other, SkinName, FaceName, 0);
		}
	}
}

I'm a bit lost here. Should I try to use Other.PlayerReplicationInfo.Deaths? BTW, thank you for replying:tup:
 

Zur

surrealistic mad cow
Jul 8, 2002
11,708
8
38
48
Code:
function ScoreKill(pawn Killer, pawn Other)
{
	local ScriptedPawn S;

	if ( (Killer == None) || (Killer == Other) || !Other.bIsPlayer 
		|| (Killer.PlayerReplicationInfo.Team != Other.PlayerReplicationInfo.Team) )
		Super.ScoreKill(Killer, Other);

Usually a gametype will pass messages on by either call the super class or calling another class directly.

The problem you might have here is that a message is only being sent to Scorekill in the Super class under certain conditions. This happens with some standard gametypes so it wouldn't be surprising.

If Scorekill isn't being called properly you can try to work around this by using other functions relating to Damage (if player health <=0 AND attacker is a monster then ...). Also, if I remember correctly, Monsterhunt places Playerpawns in one team and monsters in another.

Finally, it might also be worthwhile to see what information monsterreplicationinfo adds.
 

gopostal

Active Member
Jan 19, 2006
848
47
28
I will certainly do my homework with this and see what I can do with it. I'm a bit confused at the moment but that's fine. That's how you learn things.

Thank you for your time (which is always at a premium, I'm sure). You have given me the nudge to go in the correct direction and I *very* greatly appreciate it sir (or madam?)!
 

Zur

surrealistic mad cow
Jul 8, 2002
11,708
8
38
48
That would be sir Azura ;) (slayer of killer rabbits ?). I don't know about my time being premium but I do try to be helpful despite lack of time.

I'm back home right now so I have all my files handy. You'll find the source of Mutator.uc below. By browsing through the functions and events you should be able to figure out what's possible with mutators in general. The MutatorTakeDamage function can be used for the alternative approach I described in my last reply.

If some of the stuff I explained seems like gobbledegook, I'll say it in other terms :
- Mutator is sent a message by DeathMatchPlus, which in turn represents the game taking place.
- MonsterHunt is derived from TeamGamePlus which itself is derived from DeathMatchPlus.
- The scorekill function in a mutator is sent a message on condition that the gametype, like monsterhunt, relays it.
- The ScoreKill function can be found in a parent or super class of DeathMatchPlus named GameInfo. As you can see below, it calls a function a ScoreKill function in the BaseMutator, or very first mutator in the mutator chain, which in turn passes the message on to mutators after it.

Code:
function ScoreKill(pawn Killer, pawn Other)
{
	Other.DieCount++;
	if( (killer == Other) || (killer == None) )
		Other.PlayerReplicationInfo.Score -= 1;
	else if ( killer != None )
	{
		killer.killCount++;
		if ( killer.PlayerReplicationInfo != None )
			killer.PlayerReplicationInfo.Score += 1;
	}

	BaseMutator.ScoreKill(Killer, Other);
}

There. I hope this explains things better. It might be useful to export all the standard classes (such as Mutator) UT uses so you can browse through their code and better understand how it all works.
 

Attachments

  • Mutator.zip
    1.8 KB · Views: 2
Last edited:

playsax

New Member
Feb 20, 2008
44
0
0
I like to use MutatorTakeDamage() to detect deaths and well.. damage! :) Simply make a log() function inside that logs the details of both the Killer (InstigatedBy) and the player that Died (Victim) and you will be well on your way.

Here is some example code to get you started. It will show you the name of the actor doing damage/being hit and will also tell you if this is a player or not. If you kill yourself, it will be listed as "suicide" (this can be turned around to detect other deaths..).

Code:
function PostBeginPlay()
{
Level.Game.RegisterDamageMutator( Self ); // In order to receive damage calls, we need to register ourself as a DamageMutator.
}

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

if(InstigatedBy!=none) BroadcastMessage("Killer:"@InstigatedBy.PlayerReplicationInfo.Playername@InstigatedBy.bIsPlayer);
if(Victim!=none) BroadcastMessage("Died:"@Victim.PlayerReplicationInfo.Playername@Victim.bIsPlayer);
if(InstigatedBy!=none && InstigatedBy==Victim && Victim.PlayerReplicationInfo.Health <= 0) BroadcastMessage("A suicide!");

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

Zur

surrealistic mad cow
Jul 8, 2002
11,708
8
38
48
That's the idea.

Note that it's best to use a Super() instead of NextDamageMutator. That way the call gets sent to the Mutator parent instead of being forced on to the next mutator.

I just had a quick read through the monsterhunt source. It appears that if Scorekill is only passed on if Other is not a player. If Killer is a player, monsterhunt modifies the score and stops things there.

Since monsterhunt doesn't seem to override preventdeath, you can also try using it to get the Killed Pawn. From there on, it's a case of cycling through inventory and spawning them at the player location. Pinata should show how to do this.
 
Last edited:

gopostal

Active Member
Jan 19, 2006
848
47
28
Guys thank you so much! I have decompiled all the classes and now that you have helped me along, I can begin to see the spiderweb of parent-child that is going on. I am looking at prevent death and take damage now and I will concentrate on those to try to get the monster kills to intitiate the pinata effect.

I can see that this is going to be very important to get right. A lot of the things my group wants to do with monsterhunt will end up working like this. Thank you again for your time and effort in the explanations and code. I am getting ready to insert the log lines to decipher the damage relationships.
 

gopostal

Active Member
Jan 19, 2006
848
47
28
Just a quick update. I got the mod to work by using function bool PreventDeath. It limits the pinata effect to happen only when killed by a monster so as to not litter the ground with pickups underneath some of the tougher bunny track sections. I was hesitant to add a timer to destroy the dropped items because timers can be hard to get right.

Thank you guys again for taking time to educate me. I promise to pay it forward any chance I get.