Mod Ideas/TurnCoat
The idea is a simple one: a pickup that switches team color skins. This would of course be for team games, and would be a mutator so as to work with CTF, BR, AS, etc. The idea would be that a player from the opposite team may confuse them for a teammate... that is, until the player stole the flag or killed them.
Discussion
_Lynx|PZ
I've tried working on it, but got stuck. I've decided to do it not as a mutator, but as adrenaline combo instead. This will limit the time of skin switching, and will make it more unpredictable for the enemies, 'cause if it would be a pickup, everyone will notice that it's disappeared, and they'll start looking for a foo amongst them. First of all in StartEffect I'm getting player's team index, then change the shoulder lights' colour on it's opposite (it's simple, because they use permanent texture name), but with skins is's a whole new story. To support any skin, I need to make code versatile. I haven't found any function that changes skins depending on team color, so I tried to do this through string mumbo-jumbo, with replacing the last chracters of texture name from 1 to 0 and back. Ok, I got the name as a string, got the name, added new index and... got stuck. How do I assign the xPawn.skins[0] a value which a have as a string. So I've no idea....
Foxpaw: Have you considered walking through the Pawn list, picking a random player on the opposite team, and making the combo-using pawn mimic it? IE, set the "turncoat" to the enemy player's mesh and skins. Something like this:
simulated function Turncoat( Pawn TC ) { local Pawn Enemy; local array<Pawn> Enemies; // I'm guessing at names here, but these variables and structures do actually exist. // The names might be wrong though. Enemy = Level.Pawnlist; while( true ) { if ( /* Do some check to see if the person is not on our team. */ ) Enemies[Enemies.Length] = Enemy; Enemy = Enemy.NextPawn; // Don't recall if this is circularly linked or if it terminates with a none. // Replace with if ( Enemy == Level.Pawnlist ) as applicable. if ( Enemy == None ) break; } Enemy = Enemies[Rand( Enemies.Length )]; // Backup the turncoats mesh and junk here. // Whatever method you like. TC.LinkMesh( Enemy.Mesh ); TC.Skins = Enemy.Skins; // Not sure if this is valid, you might have to do a for loop and set each one manually. }
_Lynx: That's me again! I did it by the price of one sleepless night! But in the other way:
//============================================================================= // ComboTeamChameleon. // Copyright: Michael "_Lynx" Sokolkov ©2004 // unreal-pz@narod.ru // senninha_r@mail.ru //============================================================================= class ComboTeamChameleon extends Combo; var TeamInfo MyTeam; var class<PlayerReplicationInfo> PlayerReplicationInfoClass; var int i,NumSkins; var string CharName; var xPlayerReplicationInfo xPRI; var string cBodySkinName, SkinName, SkinNameNotex, TIndex; var material cNewBodySkinName; var xUtil.PlayerRecord rec; function PreBeginPlay() { CharName = xPawn(Owner).PlacedCharacterName; myTeam = xPawn(Owner).GetTeam(); } function StartEffect(xPawn P) { if (myTeam != none) { //======================================================= // If our player's team is red // P.S. Values of TeamIndex // 0 - the team is red // 1 - the team is blue //======================================================= if (myTeam.TeamIndex == 0) { if ( P.LeftMarker != None && !P.bInvis ) { p.LeftMarker = Spawn(class'PlayerLight',P,,P.Location); if( !P.AttachToBone(P.LeftMarker,'lshoulder') ) { log( "Couldn't attach LeftMarker to lshoulder", 'Error' ); P.LeftMarker.Destroy(); return; } P.RightMarker = Spawn(class'PlayerLight',self,,Location); if( !P.AttachToBone(P.RightMarker,'rshoulder') ) { log( "Couldn't attach RightMarker to rshoulder", 'Error' ); P.RightMarker.Destroy(); return; } P.LeftMarker.SetRelativeLocation(P.LeftOffset); P.RightMarker.SetRelativeLocation(P.RightOffset); P.RightMarker.Texture = Texture'BlueMarker_t'; p.LeftMarker.Texture = Texture'BlueMarker_t'; } else if( P.LeftMarker != None && P.bInvis ) { P.LeftMarker.Destroy(); P.RightMarker.Destroy(); } //======================================================= // And now I'll try to create some skinchnage stuff // ah... let's go... //======================================================= cBodySkinName = string(P.Skins[0]); rec = class'xUtil'.static.FindPlayerRecord(CharName); SkinName = rec.BodySkinName$"_"$0; cNewBodySkinName = Material(DynamicLoadObject(SkinName, class'Material')); P.Skins[0] = cNewBodySkinName; } //======================================================= // If our player's team is blue // P.S. Values of TeamIndex // 1 - the team is red // 0 - the team is blue //======================================================= if (myTeam.TeamIndex == 1) if ( P.LeftMarker != None && !P.bInvis ) { p.LeftMarker = Spawn(class'PlayerLight',P,,P.Location); if( !P.AttachToBone(P.LeftMarker,'lshoulder') ) { log( "Couldn't attach LeftMarker to lshoulder", 'Error' ); P.LeftMarker.Destroy(); return; } P.RightMarker = Spawn(class'PlayerLight',self,,Location); if( !P.AttachToBone(P.RightMarker,'rshoulder') ) { log( "Couldn't attach RightMarker to rshoulder", 'Error' ); P.RightMarker.Destroy(); return; } P.LeftMarker.SetRelativeLocation(P.LeftOffset); P.RightMarker.SetRelativeLocation(P.RightOffset); P.RightMarker.Texture = Texture'RedMarker_t'; p.LeftMarker.Texture = Texture'RedMarker_t'; } else if( P.LeftMarker != None && P.bInvis ) { P.LeftMarker.Destroy(); P.RightMarker.Destroy(); } cBodySkinName = string(P.Skins[0]); rec = class'xUtil'.static.FindPlayerRecord(CharName); SkinName = rec.BodySkinName$"_"$1; cNewBodySkinName = Material(DynamicLoadObject(SkinName, class'Material')); P.Skins[0] = cNewBodySkinName; } else return; } function StopEffect(xPawn P) { if (myTeam != none) { //======================================================= // If our player's team is red // P.S. Values of TeamIndex // 1 - the team is red // 0 - the team is blue //======================================================= if (myTeam.TeamIndex == 0) { if ( P.LeftMarker != None && !P.bInvis ) { p.LeftMarker = Spawn(class'PlayerLight',P,,P.Location); if( !P.AttachToBone(P.LeftMarker,'lshoulder') ) { log( "Couldn't attach LeftMarker to lshoulder", 'Error' ); P.LeftMarker.Destroy(); return; } P.RightMarker = Spawn(class'PlayerLight',self,,Location); if( !P.AttachToBone(P.RightMarker,'rshoulder') ) { log( "Couldn't attach RightMarker to rshoulder", 'Error' ); P.RightMarker.Destroy(); return; } P.LeftMarker.SetRelativeLocation(P.LeftOffset); P.RightMarker.SetRelativeLocation(P.RightOffset); P.RightMarker.Texture = Texture'RedMarker_t'; p.LeftMarker.Texture = Texture'RedMarker_t'; } else if( P.LeftMarker != None && P.bInvis ) { P.LeftMarker.Destroy(); P.RightMarker.Destroy(); } cBodySkinName = string(P.Skins[0]); rec = class'xUtil'.static.FindPlayerRecord(CharName); SkinName = rec.BodySkinName$"_"$1; cNewBodySkinName = Material(DynamicLoadObject(SkinName, class'Material')); P.Skins[0] = cNewBodySkinName; } //======================================================= // If our player's team is blue // P.S. Values of TeamIndex // 1 - the team is red // 0 - the team is blue //======================================================= if (myTeam.TeamIndex == 1) if ( P.LeftMarker != None && !P.bInvis ) { p.LeftMarker = Spawn(class'PlayerLight',P,,P.Location); if( !P.AttachToBone(P.LeftMarker,'lshoulder') ) { log( "Couldn't attach LeftMarker to lshoulder", 'Error' ); P.LeftMarker.Destroy(); return; } P.RightMarker = Spawn(class'PlayerLight',self,,Location); if( !P.AttachToBone(P.RightMarker,'rshoulder') ) { log( "Couldn't attach RightMarker to rshoulder", 'Error' ); P.RightMarker.Destroy(); return; } P.LeftMarker.SetRelativeLocation(P.LeftOffset); P.RightMarker.SetRelativeLocation(P.RightOffset); P.RightMarker.Texture = Texture'BlueMarker_t'; p.LeftMarker.Texture = Texture'BlueMarker_t'; } else if( P.LeftMarker != None && P.bInvis ) { P.LeftMarker.Destroy(); P.RightMarker.Destroy(); } cBodySkinName = string(P.Skins[0]); rec = class'xUtil'.static.FindPlayerRecord(CharName); SkinName = rec.BodySkinName$"_"$0; cNewBodySkinName = Material(DynamicLoadObject(SkinName, class'Material')); P.Skins[0] = cNewBodySkinName; } else return; }
So, I used the standard way of settings skins via xUtil. I found it the best way. Now it works ok. Thanks for the idea of the mod! I'll try to add a link to the file in next 4-5 hours.
P.S. If anyone wants to use code from this script just notify me about it, I'm interested in what you'll be doing.
_Lynx|PZ:
Here's the link to the combo Use it for save as, this should work, if click you'll probably will be sent to the site of my hoster, and the page you'll see could be in Russian...
http://unreal-pz.narod.ru/Files/TeamChameleon.zip
P.S. And who's the author of the idea? Tell me your name!
GRAF1K: Heh, this hasn't been updated since January, but in case you check back, I wrote the idea. Glad you could use it.