Replace mutator for MH

Search, find and discuss about Mutators!
User avatar
Hitman
Skilled
Posts: 170
Joined: Mon Aug 16, 2010 11:01 am
Location: Sweden

Replace mutator for MH

Post by Hitman » Mon Jul 20, 2020 2:33 pm

Is there, or can someone make a mutator that will replace all old unreal-weapons in maps including the ones that the monsters have to UT-weapons ? will appreciate if someone did one :D
Image

User avatar
EvilGrins
Godlike
Posts: 7677
Joined: Thu Jun 30, 2011 8:12 pm
Personal rank: God of Fudge
Location: Palo Alto, CA

Re: Replace mutator for MH

Post by EvilGrins » Mon Jul 20, 2020 4:35 pm

It's simpler just to edit the map.
http://unreal-games.livejournal.com/
Image
medor wrote:Replace Skaarj with EvilGrins :mrgreen:
Smilies · viewtopic.php?f=8&t=13758

User avatar
Hitman
Skilled
Posts: 170
Joined: Mon Aug 16, 2010 11:01 am
Location: Sweden

Re: Replace mutator for MH

Post by Hitman » Mon Jul 20, 2020 5:26 pm

Standard for a skaarjofficer for ex is the Unreall razorjack so you want me to edit at least 800 maps?? If they had UT-weapons it would be replaced with NW3-weapons as an ex..
Image

User avatar
sektor2111
Godlike
Posts: 4990
Joined: Sun May 09, 2010 6:15 pm
Location: On the roof.

Re: Replace mutator for MH

Post by sektor2111 » Mon Jul 20, 2020 7:12 pm

The master key is implementing in BaseMutator a good version of function "ReplaceWith", there is the problem and there I solved it, years ago. And some of those MH2 types are tempted to keep old weapons owned by monsters and... this doesn't happen all time. Aside, human player can use old weapons anyway but there will be a few errors in client due to null states called in Weapon vs TournamentWeapon if server has a weapon tweaker.

Another way would be directly adjusting function in Engine.u package and conforming it with V451 or whatever for preventing mismatch. "ReplaceWith" is a very poorly coded thing. My advice for all MH admins is to change that mess by overwriting or rewriting Engine.u or... XCGE replacement (there more other things can be solved).

The next Move for multiple replacements in cascade was another controller...
Okay, see this:

Code: Select all

function bool CheckReplacement( Actor Other, out byte bSuperRelevant)
{
	local Inventory Inv;
	local int i;
	local Pawn P;

	bSuperRelevant = 1;
	if ( Weapon(Other) != None && Weapon(Other).Instigator != None && Weapon(Other).Instigator.IsA('Pawn') )
	{
		P = Weapon(Other).Instigator;
		Other.bAlwaysRelevant = False;
		if ( P.Health > 0 && P.PlayerReplicationInfo == None )
			spawn (class'PawnControl',P,,P.Location); //Wait a bit to see what's the deal
	}
....
And PawnControl will react a bit later - "code's patience is the key, like I said elsewhere".

Code: Select all

class PawnControl expands Info;

var Pawn P;
var float Patience;

event PrebeginPlay()
{
}

event PostBeginPlay()
{
	Patience=0.15; //wait a bit to see what's the deal
}

function FinishWaiting()
{
	local Weapon W;

	if ( Pawn(Owner) != None && Pawn(Owner).Health > 0 )
		P = Pawn(Owner);

	if ( P == None || P.bDeleteMe || P.Health <= 0 )
	{
		Destroy();
		GoTo JL48;
	}

	if ( P != None && P.Weapon == None )
	{
		Foreach RadiusActors (class'Weapon',W,100,P.Location)
		{
			if ( W != None && W.Instigator == P )
			{
				W.BecomeItem();
				P.AddInventory(W);
				W.GiveAmmo(P);
			}
		}
		P.SwitchToBestWeapon();
		P.bIsPlayer = False;
	}
JL48:
}

Auto State CheckAndGo
{
Begin:
	Sleep(Patience);
DoneWaiting:
	FinishWaiting();
	LifeSpan=0.1;
}
Instigator is held in replacement - ReplaceWith is rewritten. In other hand Instigator check can be removed and taken a RespawnTime=0 or another factor initiated in replacement.

Code: Select all

function bool ReplaceWith(actor Other, string aClassName) //reworking this for different reasons
{
	local Actor A;
	local class<Actor> aClass;
	local Pawn P;
	local Weapon W;
	local Rotator DropRot;
	local bool bMarked;
	local float ORadius, OHeight;

	if ( Other.IsA('Inventory') && (Other.Location == vect(0,0,0)) )
		return false;
	ORadius = Other.CollisionRadius;
	OHeight = Other.CollisionHeight;
	Other.SetCollisionSize(1,1);
	aClass = class<Actor>(DynamicLoadObject(aClassName, class'Class', True)); //Parameter True works in XC servers - remove it out of XC...
	if ( aClass != None )
	{
		aClass.Default.bCollideWhenPlacing = False;
		A = Spawn(aClass,Other.Owner,Other.tag,Other.Location+vect(0,0,1),Other.Rotation);
	}
	else
	{
		log("Replacement Warning... unable to load"@aClassName@".",'XC_MonsterHunt');
	}
	if ( Other.IsA('Inventory') && A != None )
	{
		if ( Inventory(Other).MyMarker != None )
		{
			if ( Inventory(A) != None )
			{
				Inventory(Other).MyMarker.markedItem = Inventory(A);
				Inventory(A).SetCollisionSize(1,1);
				Inventory(A).MyMarker = Inventory(Other).MyMarker;
				A.SetLocation(Other.Location+vect(0,0,1));
				bMarked = True;
				Inventory(A).bRotatingPickup = Inventory(Other).bRotatingPickup;
				Inventory(A).RespawnTime = Inventory(Other).RespawnTime;
			}
			Inventory(Other).MyMarker = None;
		}
		else if ( A.IsA('Inventory') && Inventory(Other).Instigator != None
			&& Inventory(Other).Instigator.bIsPawn && Vsize(A.Location-Other.Instigator.Location) <= A.CollisionRadius )
		{
			Inventory(A).Respawntime = 0.0;
			Inventory(A).bHeldItem = True;
			if (Inventory(A).IsA('Weapon'))
			{
				W = Weapon(Inventory(A));
				W.PickupMessageClass = Class'Botpack.PickupMessagePlus';
				if ( Other.Instigator.Health > 0 )
				{
					P = Other.Instigator;
					W.Instigator = P;
					if ( P.FindInventoryType(aClass) == None )
					{
						if (!P.bIsPlayer)
							P.bIsPlayer=True;
						W.Touch(P);
						W.bAlwaysRelevant = False;
						if ( P.PlayerReplicationInfo == None )
							P.bIsPlayer = False;
					}
				}
			}
		}
		else
		{
			if ( !bMarked && Other.Owner == None )
			{
				if (!Level.bStartUp)
				{
					Inventory(A).RemoteRole = ROLE_DumbProxy;
					Inventory(A).bCollideWorld = True;
					DropRot = Other.Rotation;
					DropRot.Pitch = Rand(32768);
					DropRot.Yaw = Rand(65536);
					Inventory(A).Velocity = vector(DropRot) * RandRange(200,300);
					Inventory(A).Velocity.Z = RandRange(250,350);
					Inventory(A).SetPhysics(PHYS_Falling);
					Inventory(A).GotoState('Pickup', 'Dropped');
				}
				if ( bDeadBabuin )
					Inventory(A).RespawnTime = 0.00;
				else
					Inventory(A).RespawnTime = Inventory(Other).RespawnTime;
			}
			else
			{
				if ( Other.Owner != None && Other.Owner.bIsPawn )
				{
					log ("Detected a spawn "$Other$" with Owner "$Other.Owner$". Inventory will be set.");
					P = Pawn(Other.Owner);
					if ( Inventory(A).IsA('Weapon'))
					{
						W = Weapon(Inventory(A));
						W.ReSpawnTime = 0.0;
						W.BecomeItem();
						W.Instigator = P;
						P.AddInventory(W);
						W.GiveAmmo(P);
						W.WeaponSet(P);
						W.bAlwaysRelevant = False;
					}
				}
			}
		}
	}
	else
		Other.SetCollisionSize(ORadius,OHeight);

	if ( A != None )
	{
		if ( Inventory(A) != None && Inventory(A).MyMarker != None )
			A.SetCollisionSize(ORadius,OHeight);
		A.event = Other.event;
		A.tag = Other.tag;
		A.RotationRate = Other.RotationRate;
		A.bFixedRotationDir = Other.bFixedRotationDir;
		if ( Other.Base != None )
			A.SetBase(Other.Base);
//		log ( Other$" is now "$A );
		return true;
	}
	return false;
}
Code can be a bit simplified with those "A" checks... but they work in this state for years.
bDeadBabuin bool variable makes difference between weapon coming from dead pawns or from WoodenBoxes - set by game controller with function "DiscardInventory" rewritten exactly for this reason. Weapons dropped by Pawns are not respawning while those from various decorations are re-spawning if you look at TounamentWeapons not replaced and configured this way, in this case everything should have a copy reacting closer to old item.

Code: Select all

function DiscardInventory( Pawn Other )
{
	local actor dropped;
	local inventory Inv;
	local weapon weap;
	local float speed;

	if ( EMonsterBase(BaseMutator) != None )
		EMonsterBase(BaseMutator).bDeadBabuin = True;

	if( Other.DropWhenKilled != None )
	{
		dropped = Spawn(Other.DropWhenKilled,,,Other.Location);
		Inv = Inventory(dropped);
		if ( Inv != None )
		{ 
			Inv.RespawnTime = 0.0; //don't respawn
			Inv.BecomePickup();
		}
		if ( dropped != None )
		{
			dropped.RemoteRole = ROLE_DumbProxy;
			dropped.SetPhysics(PHYS_Falling);
			dropped.bCollideWorld = true;
			dropped.Velocity = Other.Velocity + VRand() * 280;
		}
		if ( Inv != None )
			Inv.GotoState('PickUp', 'Dropped');
	}
	if( (Other.Weapon!=None) && (Other.Weapon.Class != Level.Game.BaseMutator.MutatedDefaultWeapon()) 
		&& Other.Weapon.bCanThrow )
	{
		speed = VSize(Other.Velocity);
		weap = Other.Weapon;
		if (speed != 0)
			weap.Velocity = Normal(Other.Velocity/speed + 0.5 * VRand()) * (speed + 280);
		else {
			weap.Velocity.X = 0;
			weap.Velocity.Y = 0;
			weap.Velocity.Z = 0;
		}
		Other.TossWeapon();
		if ( weap.PickupAmmoCount == 0 )
			weap.PickupAmmoCount = 1;
	}
	Other.Weapon = None;
	Other.SelectedItem = None;
	for( Inv = Other.Inventory; Inv != None; Inv = Inv.Inventory )
		Inv.Destroy();

	if ( EMonsterBase(BaseMutator) != None )
		EMonsterBase(BaseMutator).bDeadBabuin = False;
}

User avatar
Hitman
Skilled
Posts: 170
Joined: Mon Aug 16, 2010 11:01 am
Location: Sweden

Re: Replace mutator for MH

Post by Hitman » Mon Jul 20, 2020 8:30 pm

I know a lot about UT but nothing about coding, so is this possible to make a mutator of ?
Image

User avatar
sektor2111
Godlike
Posts: 4990
Joined: Sun May 09, 2010 6:15 pm
Location: On the roof.

Re: Replace mutator for MH

Post by sektor2111 » Mon Jul 20, 2020 9:13 pm

Game-Type running there needs some modifications - or stock must be adjusted - if not Engine.u at least UnrealShare UnrealI can have another code for troopers. Trooper problems are coming from a bad timing of these things, Trooper is not really in timing with Weapon and doesn't know what to do if weapon is instantly replaced after spawn.

Edit: If I'm not mistaking, NaliWeapons have in ini files capability for extra-replacements configured, done by NW Mod itself. I'm not sure if that AlwaysKeep from these MH2 types is not messing up NW replacements. Even a top relevance forcing monster with old weapon - not even MonsterHunt replacements might be damaging.
Edit2: Technically in original MonsterHunt, old weapons are replaced with UT aliases, then it comes another stuff. In some of these MH2 types Monster and his weapon are making a rule - perhaps replacements must be done in other way, another code looping and checking, can be more easy by re-wrapping replacements instead of trying to fight against old codes.