If you're interested in how the colour slider works, the mathematics can be seen here:
http://en.wikipedia....iki/HSL_and_HSV
Here's how the mutator should work:
When the game starts, each player has the basic weapon - it has the rapid fire type and bullet projectile properties. When a player runs over a weapon, the player should be given the option to change the fire type to the type that the weapon they run over has (e.g, if they run over a Flak Cannon, they will be able to choose the spread fire type). When a player runs over an ammo pickup, the player should be given the option to change the projectile properties to the type of ammo they ran over (e.g if they run over a Rocket Pack, they will be able to choose to shoot Rockets).
Different combinations of all of these yield different effects.
Note that for Warfare and VCTF, when a player runs into a weapon locker, they should be able to choose from all the fire type and projectile types represented in that locker.
It'd also be cool to customise what colour the projectiles are!
Here's some really hideous code for the weapon:
class LP_KitBash_Weapon extends UTWeapon; enum FireType { eRapidFire, eSpreadFire, eSniperFire, eLockFire }; enum WeaponType { eBullet, eBioGloblet, eBioGlob, eShockBeam, eShockCore, eLinkBolt, eLinkBeam, eStinger, eStingerShard, eFlakShard, eFlakShell, eRocket, eHomingRocket }; var float DamageUpgrade, RoFUpgrade, AmmoUpgrade; var FireType WeaponFireMode; var WeaponType WeaponFireType; simulated function PostBeginPlay() { SetTypeProperties(eBullet); SetModeProperties(eRapidFire); super.PostBeginPlay(); } function SetTypeProperties(FireType WeaponFireType) { switch(WeaponFireType) { case eBullet: WeaponFireTypes[0]=EWFT_InstantHit; WeaponFireTypes[1]=EWFT_InstantHit; FireInterval[0]=1; FireInterval[1]=1; Spread[0]=1; Spread[1]=1; InstantHitDamage[0]=25; InstantHitDamage[1]=25; InstantHitMomentum[0]=1000; InstantHitMomentum[1]=1000; InstantHitDamageTypes[0]=Class'UTGame.UTDmgType_Enforcer'; InstantHitDamageTypes[1]=Class'UTGame.UTDmgType_Enforcer'; case eBioGloblet: WeaponFireTypes[0]=EWFT_Projectile; WeaponFireTypes[1]=EWFT_Projectile; FireInterval[0]=1; FireInterval[1]=1; Spread[0]=1; Spread[1]=1; WeaponProjectiles[0]=Class'MWUpgrade.LP_Proj_BioGloblet'; WeaponProjectiles[1]=Class'MWUpgrade.LP_Proj_BioGloblet'; case eBioGlob: WeaponFireTypes[0]=EWFT_Projectile; WeaponFireTypes[1]=EWFT_Projectile; FireInterval[0]=2; FireInterval[1]=2; Spread[0]=1; Spread[1]=1; WeaponProjectiles[0]=Class'MWUpgrade.LP_Proj_BioGlob'; WeaponProjectiles[1]=Class'MWUpgrade.LP_Proj_BioGlob'; case eShockBeam: WeaponFireTypes[0]=EWFT_InstantHit; WeaponFireTypes[1]=EWFT_InstantHit; FireInterval[0]=1.3; FireInterval[1]=1.3; Spread[0]=1.2; Spread[1]=1.2; InstantHitDamage[0]=32; InstantHitDamage[1]=32; InstantHitMomentum[0]=2000; InstantHitMomentum[1]=2000; InstantHitDamageTypes[0]=Class'UTGame.UTDmgType_ShockPrimary'; InstantHitDamageTypes[1]=Class'UTGame.UTDmgType_ShockPrimary'; case eShockCore: WeaponFireTypes[0]=EWFT_Projectile; WeaponFireTypes[1]=EWFT_Projectile; FireInterval[0]=2; FireInterval[1]=2; Spread[0]=1; Spread[1]=1; WeaponProjectiles[0]=Class'MWUpgrade.LP_Proj_Shock'; WeaponProjectiles[1]=Class'MWUpgrade.LP_Proj_Shock'; case eLinkBolt: WeaponFireTypes[0]=EWFT_Projectile; WeaponFireTypes[1]=EWFT_Projectile; FireInterval[0]=0.3; FireInterval[1]=0.3; Spread[0]=0.4; Spread[1]=0.4; WeaponProjectiles[0]=Class'MWUpgrade.LP_Proj_Link'; WeaponProjectiles[1]=Class'MWUpgrade.LP_Proj_Link'; case eLinkBeam: WeaponFireTypes[0]=EWFT_InstantHit; WeaponFireTypes[1]=EWFT_InstantHit; FireInterval[0]=0.7; FireInterval[1]=0.7; Spread[0]=0; Spread[1]=0; InstantHitDamage[0]=75; InstantHitDamage[1]=75; InstantHitMomentum[0]=1000; InstantHitMomentum[1]=1000; InstantHitDamageTypes[0]=Class'UTGame.UTDmgType_LinkBeam'; InstantHitDamageTypes[1]=Class'UTGame.UTDmgType_LinkBeam'; case eStinger: WeaponFireTypes[0]=EWFT_InstantHit; WeaponFireTypes[1]=EWFT_InstantHit; FireInterval[0]=0.3; FireInterval[1]=0.3; Spread[0]=1.3; Spread[1]=1.3; InstantHitDamage[0]=10; InstantHitDamage[1]=10; InstantHitMomentum[0]=1000; InstantHitMomentum[1]=1000; InstantHitDamageTypes[0]=Class'UTGame.UTDmgType_StingerBullet'; InstantHitDamageTypes[1]=Class'UTGame.UTDmgType_StingerBullet'; case eStingerShard: WeaponFireTypes[0]=EWFT_Projectile; WeaponFireTypes[1]=EWFT_Projectile; FireInterval[0]=0.2; FireInterval[1]=0.2; Spread[0]=0.45; Spread[1]=0.45; WeaponProjectiles[0]=Class'MWUpgrade.LP_Proj_StingerShard'; WeaponProjectiles[1]=Class'MWUpgrade.LP_Proj_StingerShard'; case eFlakShard: WeaponFireTypes[0]=EWFT_Projectile; WeaponFireTypes[1]=EWFT_Projectile; FireInterval[0]=0.23; FireInterval[1]=0.23; Spread[0]=0.42; Spread[1]=0.42; WeaponProjectiles[0]=Class'MWUpgrade.LP_Proj_FlakShard'; WeaponProjectiles[1]=Class'MWUpgrade.LP_Proj_FlakShard'; case eFlakShell: WeaponFireTypes[0]=EWFT_Projectile; WeaponFireTypes[1]=EWFT_Projectile; FireInterval[0]=2.2; FireInterval[1]=2.2; Spread[0]=1; Spread[1]=1; WeaponProjectiles[0]=Class'MWUpgrade.LP_Proj_FlakShell'; WeaponProjectiles[1]=Class'MWUpgrade.LP_Proj_FlakShell'; case eRocket: WeaponFireTypes[0]=EWFT_Projectile; WeaponFireTypes[1]=EWFT_Projectile; FireInterval[0]=2; FireInterval[1]=2; Spread[0]=1.2; Spread[1]=1.2; WeaponProjectiles[0]=Class'MWUpgrade.LP_Proj_Rocket'; WeaponProjectiles[1]=Class'MWUpgrade.LP_Proj_Rocket'; case eHomingRocket: WeaponFireTypes[0]=EWFT_Projectile; WeaponFireTypes[1]=EWFT_Projectile; FireInterval[0]=2.5; FireInterval[1]=2.5; Spread[0]=0.7; Spread[1]=0.7; WeaponProjectiles[0]=Class'MWUpgrade.LP_Proj_AVRIL'; WeaponProjectiles[1]=Class'MWUpgrade.LP_Proj_AVRIL'; } } function SetModeProperties(WeaponType WeaponFireMode) { switch(WeaponFireMode) { case eRapidFire: FireInterval[0] *= 0.36; //Same as the Enforcer FireInterval[1] *= 0.36; Spread[0] *= 0.03; Spread[1] *= 0.03; InstantHitDamage[0] *= 1; InstantHitDamage[1] *= 1; case eSpreadFire: FireInterval[0] *= 1.1; //Same as the Flak Cannon FireInterval[1] *= 1.1; Spread[0] *= 0.07; //Same as the Stinger (irrelevant?) Spread[1] *= 0.07; InstantHitDamage[0] *= 0.9; InstantHitDamage[1] *= 0.9; case eSniperFire: FireInterval[0] *= 1.3; //Same as the Sniper Rifle FireInterval[1] *= 1.3; Spread[0] *= 0; Spread[1] *= 0; InstantHitDamage[0] *= 2.5; InstantHitDamage[1] *= 2.5; case eLockFire: FireInterval[0] *= 0.9; FireInterval[1] *= 0.9; Spread[0] *= 0.07; //Same as the Stinger Spread[1] *= 0.07; InstantHitDamage[0] *= 1; InstantHitDamage[1] *= 1; default: FireInterval[0] *= 0.36; //Same as the Enforcer FireInterval[1] *= 0.36; Spread[0] *= 0.03; Spread[1] *= 0.03; InstantHitDamage[0] *= 1; InstantHitDamage[1] *= 1; } } DefaultProperties { ShouldFireOnRelease(0)=0 ShouldFireOnRelease(1)=0 WeaponFireTypes(0)=EWFT_InstantHit WeaponFireTypes(1)=EWFT_InstantHit FiringStatesArray(0)="WeaponFiring" FiringStatesArray(1)="WeaponFiring" WeaponProjectiles(0)=None WeaponProjectiles(1)=None FireInterval(0)=1.000000 FireInterval(1)=1.000000 Spread(0)=0.000000 Spread(1)=0.000000 InstantHitDamage(0)=0.000000 InstantHitDamage(1)=0.000000 InstantHitMomentum(0)=0.000000 InstantHitMomentum(1)=0.000000 InstantHitDamageTypes(0)=Class'Engine.DamageType' InstantHitDamageTypes(1)=Class'Engine.DamageType' ShotCost(0)=0 ShotCost(1)=0 }
and an example projectile
class LP_Proj_StingerShard extends UTProj_StingerShard; simulated function PostBeginPlay() { switch(LP_KitBash_Weapon(Owner).WeaponFireMode) { case eRapidFire: Speed *= 1; MaxSpeed *= 1; Damage *= 0.9; case eSpreadFire: Speed *= 0.7; MaxSpeed *= 0.7; Damage *= 1; case eSniperFire: Speed *= 2.5; MaxSpeed *= 2.5; Damage *= 2; case eLockFire: Speed *= 0.8; MaxSpeed *= 0.8; Damage *= 0.8; default: Speed *=1; MaxSpeed *=1; Damage *=1; } } DefaultProperties { }
Here is code for a slider that chooses a colour
class WeaponsMenu_SK extends MenuBase_SK; var transient UTUISlider uiShockBeam; event PostInitialize() { uiShockBeam = UTUISlider(FindChild('sliShockBeam', true)); uiShockBeam.SliderValue.CurrentValue = 0.f; uiShockBeam.SliderValue.MinValue = 0.f; uiShockBeam.SliderValue.MaxValue = 360.f; uiShockBeam.SliderValue.NudgeValue = 10.f; uiShockBeam.SliderValue.bIntRange = true; } function ExitMenu() { class'Pawn_SK'.default.ShockBeam = CalculateRBGfromHue(uiShockBeam.GetValue()); class'Pawn_SK'.static.StaticSaveConfig(); super.ExitMenu(); }
class Pawn_SK extends UTPawn; var LinearColor ShockBeam; defaultproperties { ShockBeam = (R=2, G=1, B=1, A=1) }
class ShockRifle_SK extends UTWeap_ShockRifle; DefaultProperties { AttachmentClass=class'ServerKing.ShockRifle_Attachment_SK' }
class Shockrifle_Attachment_SK extends UTAttachment_ShockRifle; var MaterialInstanceConstant beamMat; simulated function SpawnBeam(vector Start, vector End, bool bFirstPerson) { local ParticleSystemComponent E; local actor HitActor; local vector HitNormal, HitLocation; if ( End == Vect(0,0,0) ) { if ( !bFirstPerson || (Instigator.Controller == None) ) { return; } // guess using current viewrotation; End = Start + vector(Instigator.Controller.Rotation) * class'UTWeap_ShockRifle'.default.WeaponRange; HitActor = Instigator.Trace(HitLocation, HitNormal, End, Start, TRUE, vect(0,0,0),, TRACEFLAG_Bullet); if ( HitActor != None ) { End = HitLocation; } } MaterialInstanceConstant(BeamTemplate.Emitters[0].LODLevels[0].RequiredModule.Material).SetVectorParameterValue('BeamColour', Pawn_SK(Instigator).ShockBeam); E = WorldInfo.MyEmitterPool.SpawnEmitter(BeamTemplate, Start); E.bIsViewRelevanceDirty = TRUE; E.SetTemplate(BeamTemplate); E.SetVectorParameter('ShockBeamEnd', End); if (bFirstPerson) { E.SetDepthPriorityGroup(SDPG_Foreground); } } simulated function FirstPersonFireEffects(Weapon PawnWeapon, vector HitLocation) { local vector EffectLocation; Super.FirstPersonFireEffects(PawnWeapon, HitLocation); EffectLocation = UTWeapon(PawnWeapon).GetEffectLocation(); SpawnBeam(EffectLocation, HitLocation, true); if (!WorldInfo.bDropDetail && Instigator.Controller != None) { UTEmitterPool(WorldInfo.MyEmitterPool).SpawnExplosionLight(ImpactLightClass, HitLocation); } } simulated function ThirdPersonFireEffects(vector HitLocation) { Super.ThirdPersonFireEffects(HitLocation); SpawnBeam(GetEffectLocation(), HitLocation, false); } defaultproperties { BeamTemplate=particlesystem'ServerKingAssets.ShockRifle.P_ShockRifle_Beam' WeaponClass=class'ServerKing.ShockRifle_SK' }
Comments and criticism?