Replacing player's weapon

Discussions about Coding and Scripting
Post Reply
Kismet
Novice
Posts: 10
Joined: Sat Nov 05, 2022 9:45 pm

Replacing player's weapon

Post by Kismet »

I write a mutator in which I need to replace any weapon of a certain type (eg. SniperRifle) with another (eg. MySuperRifle). It should work both for weapons which appear in the ground, and for weapons given to players at level start, for example like in the mode "Last Man Standing".

My code:

Code: Select all

function bool CheckReplacement(Actor other, out byte bSuperRelevant) {
	local Weapon weapon;
	local bool is_inventory_weapon;
	local Pawn owner;
	
	if (other.Class == class'SniperRifle') {
		weapon = Weapon(other);
		
		is_inventory_weapon = ... // how to determine what current weapon is in inventory?
		owner = ... // how to determine the owner (player and bot) of the current weapon?
		
		if (is_inventory_weapon) {
			SpawnWeaponInInventory(owner, class'MySuperRifle'); // for inventory weapons
		} else {
			ReplaceWith(other, string(class'MySuperRifle')); // for ground weapons
		}
		
		return false;
	}
	return true;
}

function SpawnWeaponInInventory(Pawn pawn, class<Weapon> weapon_class) {
	local Weapon weapon;
	
	weapon = Spawn(weapon_class);
	if (weapon != none) {
		weapon.GiveTo(pawn);
		weapon.GiveAmmo(pawn);
		// is it enough for correct spawning?
	}
}
Please answer the questions in the comments in the code above.
User avatar
ExpEM
Adept
Posts: 298
Joined: Wed Nov 09, 2016 1:48 am

Re: Replacing player's weapon

Post by ExpEM »

Have a look at DMMutator, it replaces all Unreal classes with the UT equivalents, so, exactly what you want to do really.
Signature goes here.
Kismet
Novice
Posts: 10
Joined: Sat Nov 05, 2022 9:45 pm

Re: Replacing player's weapon

Post by Kismet »

Didn't help me. DMMutator uses ReplaceWith() method. It is not work for weapons in the inventory.

For example, ChaosUT mutator (replaces all weapons) also don't work in the mode LastManStanding. It also replaces only ground weapons.
User avatar
EvilGrins
Godlike
Posts: 9744
Joined: Thu Jun 30, 2011 8:12 pm
Personal rank: God of Fudge
Location: Palo Alto, CA
Contact:

Re: Replacing player's weapon

Post by EvilGrins »

ExpEM wrote: Tue Oct 17, 2023 7:37 am Have a look at DMMutator, it replaces all Unreal classes with the UT equivalents, so, exactly what you want to do really.
I need that mutator, lots of Thunderbolts maps have both U1 & ut99 versions. It's annoying!
Attachments
Shot0031.png
http://unreal-games.livejournal.com/
Image
medor wrote:Replace Skaarj with EvilGrins :mrgreen:
Smilies · viewtopic.php?f=8&t=13758
User avatar
ExpEM
Adept
Posts: 298
Joined: Wed Nov 09, 2016 1:48 am

Re: Replacing player's weapon

Post by ExpEM »

Kismet wrote: Wed Oct 18, 2023 7:58 am Didn't help me. DMMutator uses ReplaceWith() method. It is not work for weapons in the inventory.

For example, ChaosUT mutator (replaces all weapons) also don't work in the mode LastManStanding. It also replaces only ground weapons.
I did some testing and see what you mean. I don't play LMS so I didn't realise normal Weapon replacement was broken.
I tested with PSI Weapons Dreams that was broken, however NaliWeapons3 isn't broken and works fine.
I honestly have no idea how half of Feralidragons code works but he figured it out so hit him up if he is still around.
The static functions (Find Static) in NWCoreVIII.NWReplacer seem to do it but again idk how. :noidea
Feralidragon is a god of code (and hates it when you call him that).

I'll do some testing and see what I can come up with.
Signature goes here.
User avatar
Barbie
Godlike
Posts: 2808
Joined: Fri Sep 25, 2015 9:01 pm
Location: moved without proper hashing

Re: Replacing player's weapon

Post by Barbie »

I think LMS will not work proper with a Mutator: LMS.RestartPlayer() calls LMS.AddDefaultInventory() which gives all UT weapons to a player:

Code: Select all

function AddDefaultInventory( pawn PlayerPawn ) {
	...
	GiveWeapon(PlayerPawn, "Botpack.ShockRifle");
	GiveWeapon(PlayerPawn, "Botpack.UT_BioRifle");
	...
function GiveWeapon() is in parent class DeathMatchPlus: it spawns the desired weapon and uses Weapon.GiveTo() to transfer it to the player.
  • If you use Mutator.CheckReplacement() here, DeathMatchPlus.GiveWeapon() will fail silently and the player will not have that weapon.
  • Also Mutator.RestartPlayer() will not work because LMS.RestartPlayer() does NOT call its parent class function which in turn would have called Mutator.RestartPlayer().
I recommend using class'SpawnNotify', which can be created by your Mutator while a map is loaded.
"Multiple exclamation marks," he went on, shaking his head, "are a sure sign of a diseased mind." --Terry Pratchett
User avatar
papercoffee
Godlike
Posts: 10451
Joined: Wed Jul 15, 2009 11:36 am
Personal rank: coffee addicted !!!
Location: Cologne, the city with the big cathedral.
Contact:

Re: Replacing player's weapon

Post by papercoffee »

I tested LMS with Food Fight, it worked somehow.
It didn't gave you all weapons but only the start weapons. Frying Pan and the Canopener (pistol).
I think I used Stuff Swapper for this...
Kismet
Novice
Posts: 10
Joined: Sat Nov 05, 2022 9:45 pm

Re: Replacing player's weapon

Post by Kismet »

FoodFight just forcibly gives its weapons (declared in ini-file) even when the game doesn't give. So in LMS I get double weapons in each slot - default and FoodFight-weapon. This is very easy to implement. And it's not a solution. I tested FoodFight MHversion (https://unrealarchive.org/mutators/unre ... b1a02.html).

I haven't much experience with the class SpawnNotify. But I think it cann't help me. Maybe I'm wrong.

NW3 replaces weapons correctly but I didn't found yet an answer for my question in its sources.
User avatar
Barbie
Godlike
Posts: 2808
Joined: Fri Sep 25, 2015 9:01 pm
Location: moved without proper hashing

Re: Replacing player's weapon

Post by Barbie »

Kismet wrote: Thu Oct 19, 2023 7:01 pm I haven't much experience with the class SpawnNotify. But I think it cann't help me. Maybe I'm wrong.
See this:

Code: Select all

//=============================================================================
// MySpawnNotify.
//=============================================================================
class MySpawnNotify expands SpawnNotify;


simulated event Actor SpawnNotification(Actor A) {
local String NewWeapon;
local Actor Result;

	log("MySpawnNotify: SpawnNotification called with" @ A);
	if (A.Class == Class'ShockRifle')
		NewWeapon = "bPak.bShock";
	else if (A.Class == Class'UT_Eightball')
		NewWeapon = "bPak.bEightball";
	// ...

	if (NewWeapon != "")
	{
		Result = spawn(Class<Actor>(DynamicLoadObject(NewWeapon, class'Class')), , , A.Location);
		if (Result != None)
		{
			log("MySpawnNotify: spawned" @ result);
			A.Destroy();
			return Result;
		}
	
	}
	return A;
}
I set MySpawnNotify.ActorClass to "Class'Botpack.TournamentWeapon'" manually in UnrealEd in the attached example.

It replaces "BotPack.ShockRifle" with "bPak.bShock", "UT_Eightball" with "bPak.bEightball", ... Of course you need to have package "bPak" in one of your UT paths.
UnrealTournament.log wrote:ScriptLog: MySpawnNotify: SpawnNotification called with Autoplay.enforcer0
ScriptLog: MySpawnNotify: SpawnNotification called with Autoplay.ImpactHammer0
ScriptLog: MySpawnNotify: SpawnNotification called with Autoplay.Translocator0
ScriptLog: MySpawnNotify: SpawnNotification called with Autoplay.ShockRifle0
ScriptLog: MySpawnNotify: spawned Autoplay.BShock0
ScriptLog: MySpawnNotify: SpawnNotification called with Autoplay.ut_biorifle0
ScriptLog: MySpawnNotify: SpawnNotification called with Autoplay.ripper0
ScriptLog: MySpawnNotify: SpawnNotification called with Autoplay.UT_FlakCannon0
ScriptLog: MySpawnNotify: SpawnNotification called with Autoplay.SniperRifle0
ScriptLog: MySpawnNotify: SpawnNotification called with Autoplay.PulseGun1
ScriptLog: MySpawnNotify: SpawnNotification called with Autoplay.minigun0
ScriptLog: MySpawnNotify: SpawnNotification called with Autoplay.UT_Eightball0
ScriptLog: MySpawnNotify: spawned Autoplay.BEightball0
Attachments
WeaponReplacer.unr.7z
(3.55 KiB) Downloaded 7 times
"Multiple exclamation marks," he went on, shaking his head, "are a sure sign of a diseased mind." --Terry Pratchett
Kismet
Novice
Posts: 10
Joined: Sat Nov 05, 2022 9:45 pm

Re: Replacing player's weapon

Post by Kismet »

SpawnNotify is very useful to solve my problem. Thank you.

But while I tested it, several questions accumulated.

1. You use Spawn(class<>,..., A.Location). And I expected if I change coordinates then the weapon to be created at the specified location (eg. Spawn(class<>,..., vect(x, y, z))). But the weapon always spawns in inventory. I ask because Spawn function doesn't have inventory-specific information.

2. After we spawned (with Spawn()) a new TournamentWeapon, our SpawnNotify class doesn't call SpawnNotification() for this new weapon. Why? I thought Spawn() function must generate for each "spawn" event.

3. I made a mutator, which creates (spawns) my SpawnNotify instance in PreBeginPlay() function. But weapons that are generated on the ground doesn't call SpawnNotification(). Why?

4. SpawnNotification is triggered both when weapon is issued at player respawn, and when weapon picked up first time. But in respawn weapon's property Owner is set to None. Why?

5. You say that you set ActorClass manually in UnrealEd, but I didn't find this property in your sample map. Besides property ActorClass is not marked as var(). How do you change it in UnrealEd? (just to know about UnrealEd; I set it in uc-files)
User avatar
Barbie
Godlike
Posts: 2808
Joined: Fri Sep 25, 2015 9:01 pm
Location: moved without proper hashing

Re: Replacing player's weapon

Post by Barbie »

Kismet wrote: Fri Oct 20, 2023 5:45 am 1. You use Spawn(class<>,..., A.Location). And I expected if I change coordinates then the weapon to be created at the specified location (eg. Spawn(class<>,..., vect(x, y, z))). But the weapon always spawns in inventory. I ask because Spawn function doesn't have inventory-specific information.
See code in my first post: GiveWeapon() asks (spawns) for a new weapon, SpawnNotify gives back another, and GiveWeapon() puts it into player's inventory.
Kismet wrote: Fri Oct 20, 2023 5:45 am 2. After we spawned (with Spawn()) a new TournamentWeapon, our SpawnNotify class doesn't call SpawnNotification() for this new weapon. Why? I thought Spawn() function must generate for each "spawn" event.
I guess that notification is disabled for this instance while processing event SpawnNotification(). Otherwise an endless loop might be created.
Kismet wrote: Fri Oct 20, 2023 5:45 am 3. I made a mutator, which creates (spawns) my SpawnNotify instance in PreBeginPlay() function. But weapons that are generated on the ground doesn't call SpawnNotification(). Why?
Probably they exist before your SpawnNotify is created. You can test that by adding a log-all-actors-of-interest in an Auto State of SpawnNotify.
But you may catch them by Mutator's CheckReplacement().
Kismet wrote: Fri Oct 20, 2023 5:45 am 4. SpawnNotification is triggered both when weapon is issued at player respawn, and when weapon picked up first time. But in respawn weapon's property Owner is set to None. Why?
Idk. Is it also None when not using replacement?
The owner is set by this chain: DeathMatchPlus.GiveWeapon(newWeapon) calls newWeapon.GiveTo(pawn Other) what calls parent's Inventory.GiveTo(pawn Other) what calls Pawn.AddInventory(self) what finally calls NewItem.SetOwner(Self).
Probably it helps if you set the owner in SpawnNotification:

Code: Select all

if (NewWeapon != "")
	{
		Result = spawn(Class<Actor>(DynamicLoadObject(NewWeapon, class'Class')), , , A.Location);
		if (Result != None)
		{
			Result.SetOwner(A.Owner);
			A.Destroy();
			return Result;
		}
Kismet wrote: Fri Oct 20, 2023 5:45 am 5. You say that you set ActorClass manually in UnrealEd, but I didn't find this property in your sample map. Besides property ActorClass is not marked as var(). How do you change it in UnrealEd? (just to know about UnrealEd; I set it in uc-files)
SpawnNotify.ActorClass.jpg
SpawnNotify.ActorClass.jpg (35.85 KiB) Viewed 557 times
"Multiple exclamation marks," he went on, shaking his head, "are a sure sign of a diseased mind." --Terry Pratchett
Kismet
Novice
Posts: 10
Joined: Sat Nov 05, 2022 9:45 pm

Re: Replacing player's weapon

Post by Kismet »

1. Ok, I understand. We used "Location" and this is not relevant for inventory weapons. All that remains is to figure out how to create SpawnNotification() for the ground weapons.
3. No. I tested it right away. Ground weapons call CheckReplacement() after SpawnNotify creation.
4. We can't set the owner in SpawnNotification because we already get "A" with empty Owner property (for all "player respawn" weapons; eg Hammer/Enforcer in DM mode and all weapons in LMS mode).
5. I don't have "Hidden Properties". What version of UT do you use? Anyway it looks like a small programming hack because we can change "private" properties (not marked as var()) but it might be convenient for quick testing.
User avatar
Leo(T.C.K.)
Inhuman
Posts: 875
Joined: Sat Aug 13, 2011 10:26 pm

Re: Replacing player's weapon

Post by Leo(T.C.K.) »

Hidden Properties is implemented in 227j and I guess some of the last 469 patches.
All it does is show the stuff previously known as "none" if you do editactor class= command in the game.

But a LOT of UT stuff has properties hidden that should be configurable within the editor and only is useful if you code from scratch with uc files.

Also...we used to do a lot of mutator hackery in the past including messing with/replacing the replacewith function that transfers more properties over and such but this is more useful for coop/sp. But a LOT can be done with mutators really. Like I kept updating 3's coop until he stopped the server (twice over now, he returned in recent years but stopped with it this year again).

But yea like isn't even the defaultweapon stuff hidden by default also? That normally you can replace? I'm not sure now, don't have the game on this thing for me to look.

LMS is indeed more tricky because it just gives the player the weapons on the spot. Of course if there is recursive replacement this won't matter but might result in floating weapons if done incorrectly. There are all kind of ways to go around it.
Post Reply