1389 lines
48 KiB
Ucode
1389 lines
48 KiB
Ucode
class a_MonsterOptimizer extends a_ActorBase
|
|
config(HideMut);
|
|
|
|
var PlayerController PC;
|
|
var float NumSequences;
|
|
var int NewTicks, CurrentZone; // for tick comparing
|
|
var bool Opt_Launched, // optimizer started
|
|
LowGore, // Client Low Gore == KillingFloor.ini, parameter UseLowGore
|
|
Cooldown; // Flag for ZoneInfo zed search
|
|
var int NumZeds, // Num spawned Zeds
|
|
NumberOfZonesChecked; // Number of checked zones
|
|
var array<KFMonster> cachedZeds; // cache zeds for culling and other purposes
|
|
var array<KFMonster> deadZeds; // cache zeds for ragdoll management
|
|
var array<ZoneInfo> ZoneInfos;
|
|
var ZoneInfo Zone;
|
|
|
|
// ========================= Configz
|
|
var config array<string> KFMonsterGibClassNames; // Gibs aka severed arms
|
|
var config array<string> KFMonsterGibletsClassNames; // giblets - small parts that spawn when arm, leg or etc. has been lost
|
|
var config array<string> KFMonsterGibEmitters; // 5000 tons of bloods and particles...
|
|
|
|
var config array<string> KFMonsterClassNames_Standard, // default monster classes
|
|
KFMonsterClassNames_Circus, // Circus
|
|
KFMonsterClassNames_Halloween, // Halloween
|
|
KFMonsterClassNames_XMas; // Xmas
|
|
var config array<string> CustomZeds; // Scrn zeds
|
|
var config array<string> NiceZeds; // NiceZeds
|
|
var config array<string> LagEmitters; // Firebug shit
|
|
|
|
var config array<string> TWIGoreBackup, TWIGibEmitters;
|
|
|
|
// =============================== Structures for optimizer paramas
|
|
struct EmitLightControl
|
|
{
|
|
var bool UseFireTweaks; // Use or not fire tweaks
|
|
var float LightRadius; // Light radius for fire emitters
|
|
var ELightType LightType; // Light tyoe
|
|
var byte LightBrightness;
|
|
var byte LightHue; // Color
|
|
var byte LightSaturation;
|
|
var bool bDynamicLight; // Should be dynamic?
|
|
var bool bSpecialLit; // Don't lit dynamic actors
|
|
var bool UseAdditionalTweaks; // Use additional tweaks flashlight and etc.
|
|
var bool FixDoshLighting; // Attempt to fix dosh mesh lighting
|
|
};
|
|
|
|
// for ambient sounds
|
|
struct OptParams
|
|
{
|
|
var string WholeMapSearchMethod; // Use zoneinfo.zoneactors search or use DynamicActors search
|
|
var bool ConsNetSpeed; // Constant net speed
|
|
var bool bMonsterSpotted;
|
|
|
|
var float ZedCullDistance; // Cull distance for zeds
|
|
var float Timer;
|
|
var int Ticks; // every goddamn tick optimizer will detect decapped zeds
|
|
var int nozed_NetSpeed; // NetSpeed without zeds
|
|
var int new_NetSpeed; // NetSpeed with zeds
|
|
var bool UseUnlit; // if unlit zed will appear in full brightness
|
|
var byte AmbientGlow; // if unlit this will regulate zed's brightness
|
|
var bool bSeasonedOff; // disable season zeds //replace seasoned(super laggy) zeds with default. Fuk u twi
|
|
// for 70 bones skeletons and MSM_Smooth_Only shit. Read dat fucking manual first
|
|
var bool bLagOff;
|
|
var ESoundOcclusion SoundOcclusion; // Sound occlusion == what will block sounds(bsp, static meshes, none and etc)
|
|
var float SoundRadius; // Ambient Sound radius
|
|
// ===================== Seasoned zeds shit
|
|
var bool bStandard;
|
|
var bool bCircus;
|
|
var bool bHillBilly;
|
|
var bool bXmas;
|
|
// ===================== Seasoned zeds shit
|
|
|
|
// ================================ Gore related tweaks
|
|
var string GoreLevel; // my gore level preset for twi classes
|
|
// Gibs
|
|
var bool bNoRagdolls; // Destroy Ragdolls them
|
|
var float RagdollLifeSpan;
|
|
var bool bAdvancedGibs;
|
|
var bool bUnlitGibs;
|
|
var bool bHideGibs;
|
|
var float GibsLifespan;
|
|
var bool GibUseDeferRendering;
|
|
var int GibMaxLights;
|
|
var bool GibUseCollisionStaticMesh;
|
|
var bool GibAcceptProjectors;
|
|
var bool GibStaticLighting;
|
|
|
|
// Giblets
|
|
var bool bAdvancedGiblets;
|
|
var bool bUnlitGiblets;
|
|
var bool bHideGiblets;
|
|
var float GibletsLifespan;
|
|
var bool GibletsUseDeferRendering;
|
|
var int GibletsMaxLights;
|
|
var bool GibletsUseCollisionStaticMesh;
|
|
var bool GibletsAcceptProjectors;
|
|
var bool GibletsStaticLighting;
|
|
|
|
// =============================== Gore related tweaks end
|
|
var bool UserSettingsToEmitters;
|
|
var int ZedSearchRadius;
|
|
};
|
|
|
|
// Emitter backups. Stub. Should rewrite dis
|
|
// contains variables from Particle emitter class. Used to backup and edit particle emitter classes
|
|
struct EMB
|
|
{
|
|
var string ClassName; //Particle emitter name
|
|
var bool bHidden;
|
|
var bool bUnlit;
|
|
var bool Disabled; //Disable Emitter
|
|
var float InitialParticlesPerSecond; //plz make it 500000000000000000000
|
|
var bool UseCollision; //Use collision for emitter particles
|
|
var bool AcceptsProjectors; //Accept projectors or don't
|
|
var float LifeSpan;
|
|
};
|
|
|
|
struct EMP_backups
|
|
{
|
|
var string ClassName;
|
|
var bool bHidden;
|
|
var bool bUnlit;
|
|
var float LifeSpan; //lifespan applies to emitter class
|
|
var array<EMB> CEMP; //particle emitters array
|
|
};
|
|
|
|
struct GorePresets //Gore presets for my emitters
|
|
{
|
|
var string PresetName;
|
|
var string PresetDescription;
|
|
var array<EMP_backups> EmittersToLoad;
|
|
};
|
|
|
|
//===============================Structures for optimizer paramas
|
|
var OptParams CurrentOptParams; //Current optimizer parameters
|
|
var EmitLightControl LC; //Firebug and lighting shit also dosh meshlighting fix
|
|
var EMP_backups EMP_backSingle; //for backuping emitters properties, single emitter
|
|
var array<EMP_backups> EMP_back; //for backuping emitters properties, emitters array
|
|
var EMB User_EMPS; //User settings for all emitters
|
|
var array<GorePresets> Gore_Presets; //Gore_Presets. mb should add custom?
|
|
var GorePresets Gore_Preset; //Single Gore Preset for using in structure arrays
|
|
|
|
var array<class <Emitter> > BackupGore, LowGoreE, OptGore, NoGore;
|
|
|
|
function startOptimize()
|
|
{
|
|
local int i;
|
|
|
|
PC = Level.GetLocalPlayerController();
|
|
|
|
// Zone infos stuff only dependent to ZoneActors search method
|
|
if (CurrentOptParams.WholeMapSearchMethod ~= "ZoneActors")
|
|
{
|
|
CurrentZone = 0;
|
|
ForEach AllActors(class'ZoneInfo', Zone)
|
|
{
|
|
//PC.ClientMessage(PC.GameReplicationInfo.PRIArray.length);
|
|
ZoneInfos[i] = Zone;
|
|
i++;
|
|
}
|
|
|
|
for(i=0;i<ZoneInfos.length;i++)
|
|
{
|
|
if (ZoneInfos[i] == none
|
|
|| Instr(CAPS(string(ZoneInfos[i])), "SKY") != -1
|
|
|| Instr(CAPS(string(ZoneInfos[i])), "ROCKING") != -1
|
|
|| Instr(CAPS(string(ZoneInfos[i])), "WARP") != -1
|
|
|| Instr(CAPS(string(ZoneInfos[i])), "LEVEL") != -1)
|
|
ZoneInfos.Remove(i,1);
|
|
//PC.ClientMessage(ZoneInfos[i]);
|
|
}
|
|
|
|
if (ZoneInfos.length == 0)
|
|
{
|
|
CurrentOptParams.WholeMapSearchMethod = "AllActors";
|
|
PC.ClientMEssage("No zones. Using All actors method");
|
|
}
|
|
}
|
|
|
|
if (CurrentOptParams.bSeasonedOff)
|
|
RemoveSeasonedZeds();
|
|
else
|
|
RestoreSeasonedZeds();
|
|
|
|
LowGore = class'GameInfo'.static.UseLowGore(); //Client Low Gore == KillingFloor.ini, parameter UseLowGore
|
|
OptimizeGore(); //Optimize gibs and gilets
|
|
if (LC.UseFireTweaks)
|
|
FirebugDisabler(); //Disable firebug shit
|
|
|
|
// Additional tweaks
|
|
if (LC.UseAdditionalTweaks)
|
|
{
|
|
class'SingleAttachment'.default.LightType = LT_Steady; //Why dafuq you put LT_Pulse on flashlight.
|
|
class'ZEDMKIIPrimaryProjectileImpact'.default.LightType = LT_Steady;
|
|
class'ZEDMKIISecondaryProjectileExplosion'.default.LightType = LT_Steady;
|
|
class'ZEDProjectileImpact'.default.LightType = LT_Steady;
|
|
}
|
|
|
|
// Dosh tweak, Remove crazy mesh lighting dosh shit
|
|
if (LC.FixDoshLighting)
|
|
class'KFMod.CashPickup'.default.bUnlit = true;
|
|
|
|
if (!Opt_Launched)
|
|
{
|
|
// Don't start timer if using default class pollution
|
|
if (CurrentOptParams.bLagOff)
|
|
PolluteDefaults(false);
|
|
else
|
|
{
|
|
SetTimer(CurrentOptParams.Timer, true);
|
|
Opt_Launched = true;
|
|
if (!LowGore)
|
|
Disable('Tick');
|
|
else
|
|
Enable('Tick');
|
|
}
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
stopOptimize();
|
|
Opt_Launched = true;
|
|
// Don't start timer if using non-laggy optimization
|
|
if (!CurrentOptParams.bLagOff)
|
|
SetTimer(CurrentOptParams.Timer, true);
|
|
if (!LowGore)
|
|
Disable('Tick');
|
|
else
|
|
Enable('Tick');
|
|
}
|
|
}
|
|
|
|
function stopOptimize()
|
|
{
|
|
local int i;
|
|
|
|
SetTimer(0.00, false);
|
|
Disable('Tick');
|
|
ZoneInfos.length = 0;
|
|
|
|
Opt_Launched = false;
|
|
// Restoring defaults on cached zeds
|
|
if (cachedZeds.Length != 0)
|
|
{
|
|
for (i=0; i<cachedZeds.Length; i++)
|
|
{
|
|
if (cachedZeds[i] == none)
|
|
{
|
|
cachedZeds.Remove(i,1);
|
|
continue;
|
|
}
|
|
cachedZeds[i].cullDistance = 0;
|
|
cachedZeds[i].bUnlit = false;
|
|
cachedZeds[i].AmbientGlow = 0;
|
|
cachedZeds[i].SoundOcclusion = Occlusion_Default;
|
|
cachedZeds[i].SoundRadius = 300;
|
|
}
|
|
cachedZeds.Length = 0;
|
|
}
|
|
// Restoring defaults on dead zeds
|
|
if (deadZeds.Length != 0)
|
|
{
|
|
for (i=0; i<deadZeds.Length; i++)
|
|
{
|
|
if (deadZeds[i] == none)
|
|
{
|
|
deadZeds.Remove(i,1);
|
|
continue;
|
|
}
|
|
deadZeds[i].LifeSpan = 8.5;
|
|
}
|
|
deadZeds.length = 0;
|
|
}
|
|
|
|
if (CurrentOptParams.bLagOff)
|
|
{
|
|
// default actor values
|
|
PolluteDefaults(true);
|
|
}
|
|
if (CurrentOptParams.bSeasonedOff)
|
|
RestoreSeasonedZeds();
|
|
|
|
GibAndGibletsTweaks(true);
|
|
}
|
|
|
|
function Timer()
|
|
{
|
|
NumSequences = NumSequences + 1;
|
|
|
|
cacheZeds(); //Get zeds on client and cache them to array
|
|
//PC.ClientMEssage("Zeds on map: " @ cachedZeds.length);
|
|
|
|
if(CurrentOptParams.new_NetSpeed > 0 && CurrentOptParams.nozed_NetSpeed > 0) //Change my netspeed
|
|
NetSpeedChanger();
|
|
|
|
if(cachedZeds.length > 0) //use cooling only if there are zeds and client "saw" them.
|
|
{
|
|
//Apply our shit
|
|
CullZedsOnMap(); //for wave based maps use KFGameReplicationInfo(myKFPC.GameReplicationInfo).MaxMonsters
|
|
}
|
|
if(deadZeds.length > 0)
|
|
{
|
|
ControlRagdolls(); //for ragdoll controlling
|
|
}
|
|
}
|
|
|
|
simulated function Tick(float Delta)
|
|
{
|
|
if(CurrentOptParams.Ticks == 0)
|
|
return;
|
|
NewTicks++;
|
|
if (NewTicks == CurrentOptParams.Ticks)
|
|
{
|
|
DetectHeadless();
|
|
}
|
|
}
|
|
|
|
// Cache Spawned Zeds
|
|
simulated function cacheZeds()
|
|
{
|
|
local KFMonster KFM;
|
|
local int i;
|
|
|
|
if (KFGameReplicationInfo(PC.GameReplicationInfo).TimeToNextWave > 0) //Don't work on trader time
|
|
{
|
|
cachedZeds.length = 0; //And destroy cached on previous wave zeds if they exist
|
|
return;
|
|
}
|
|
|
|
if (PC.AcknowledgedPawn == none && CurrentOptParams.WholeMapSearchMethod != "ZoneActors") //Do not work if we dont have pawn however zoneinfo search will work
|
|
return; //Incase of spectating with my stuff turned on
|
|
|
|
switch (CurrentOptParams.WholeMapSearchMethod)
|
|
{
|
|
case "AllActors":
|
|
ForEach PC.AcknowledgedPawn.AllActors(class'KFMonster', KFM)
|
|
{
|
|
if(KFM.Physics == PHYS_KarmaRagdoll) // cache this to dead zeds
|
|
{
|
|
deadZeds[deadZeds.length] = KFM;
|
|
}
|
|
else // cache this to alive zeds
|
|
{
|
|
if(KFM.CullDistance != CurrentOptParams.ZedCullDistance) //if we having culldistance property on a Monster => it is already been cached
|
|
{
|
|
cachedZeds[cachedZeds.length] = KFM;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
case "ZoneActors":
|
|
if(!CoolDown && PC.PlayerReplicationInfo.PlayerZone != none) //Wait for cooldown
|
|
{
|
|
for(i=0; i<ZoneInfos.Length; i++)
|
|
{
|
|
if(ZoneInfos[i] == PC.PlayerReplicationInfo.PlayerZone); //Let's start with player zone then check other zones
|
|
CurrentZone = i; //Save index
|
|
}
|
|
CoolDown = true;
|
|
}
|
|
ForEach ZoneInfos[CurrentZone].ZoneActors(class'KFMonster', KFM)
|
|
{
|
|
if (KFM.Physics == PHYS_KarmaRagdoll) //cache this to dead zeds
|
|
{
|
|
deadZeds[deadZeds.length] = KFM;
|
|
}
|
|
else //cache this to alive zeds
|
|
{
|
|
if (KFM.CullDistance != CurrentOptParams.ZedCullDistance) //if we having culldistance set on a Monster => it is already been cached
|
|
{
|
|
cachedZeds[cachedZeds.length] = KFM;
|
|
//PC.ClientMEssage("Was cached" @ CachedZeds.Length @ "zeds");
|
|
}
|
|
}
|
|
NumberOfZonesChecked++;
|
|
}
|
|
//PC.ClientMessage(cachedZeds.length @ deadZeds.length);
|
|
CurrentZone++;
|
|
if (NumberOfZonesChecked == ZoneInfos.length - 1) //back to checking player zone
|
|
{
|
|
Cooldown = false;
|
|
NumberOfZonesChecked = 0;
|
|
}
|
|
if (CurrentZone >= ZoneInfos.length)
|
|
CurrentZone = 0;
|
|
|
|
break;
|
|
|
|
case "DynamicActors":
|
|
forEach PC.AcknowledgedPawn.DynamicActors(class'KFMonster', KFM)
|
|
{
|
|
if (KFM.Physics == PHYS_KarmaRagdoll) //cache this to dead zeds
|
|
{
|
|
deadZeds[deadZeds.length] = KFM;
|
|
}
|
|
// cache this to alive zeds
|
|
else
|
|
{
|
|
// if we having culldistance set on a Monster => it is already been cached
|
|
if (KFM.CullDistance != CurrentOptParams.ZedCullDistance)
|
|
{
|
|
cachedZeds[cachedZeds.length] = KFM;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case "RadiusActors":
|
|
foreach PC.AcknowledgedPawn.CollidingActors(class'KFMonster', KFM, CurrentOptParams.ZedSearchRadius)
|
|
{
|
|
// cache this to dead zeds
|
|
if (KFM.Physics == PHYS_KarmaRagdoll)
|
|
{
|
|
deadZeds[deadZeds.length] = KFM;
|
|
}
|
|
// cache this to alive zeds
|
|
else
|
|
{
|
|
// if we having culldistance set on a Monster => it is already been cached
|
|
if (KFM.CullDistance != CurrentOptParams.ZedCullDistance)
|
|
{
|
|
cachedZeds[cachedZeds.length] = KFM;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
// Apply our tweaks to cached zeds
|
|
simulated function CullZedsOnMap()
|
|
{
|
|
local int i;
|
|
local KFMonster KFM;
|
|
|
|
for(i = 0; i < cachedZeds.length; i++)
|
|
{
|
|
if(cachedZeds[i] == none || cachedZeds[i].Health <= 0) //Remove killed zeds
|
|
{
|
|
cachedZeds.Remove(i,1);
|
|
continue;
|
|
}
|
|
KFM = cachedZeds[i];
|
|
if(KFM == none) //none check
|
|
continue;
|
|
if(CurrentOptParams.bMonsterSpotted) //&& int(NumSequences%2)>0)
|
|
{
|
|
MonsterSpotted(KFM); //REMOVE IT
|
|
}
|
|
|
|
if(KFM.cullDistance != CurrentOptParams.ZedCullDistance)
|
|
{
|
|
KFM.cullDistance = CurrentOptParams.ZedCullDistance;
|
|
KFM.bUnlit = CurrentOptParams.UseUnlit;
|
|
KFM.AmbientGlow = CurrentOptParams.AmbientGlow;
|
|
KFM.SoundOcclusion = CurrentOptParams.SoundOcclusion;
|
|
KFM.SoundRadius = CurrentOptParams.SoundRadius;
|
|
}
|
|
}
|
|
}
|
|
|
|
simulated function MonsterSpotted(KFMOnster KFMO) //Remove IT
|
|
{
|
|
local string KFMonsterST;
|
|
|
|
if(KFMO == none)
|
|
return;
|
|
|
|
KFMonsterST = string(KFMO);
|
|
|
|
if(Instr(caps(KFMonsterST), "STALKER") != -1 && !KFMO.bSpotted)
|
|
{
|
|
KFMO.Skins[0] = Finalblend'KFX.StalkerGlow';
|
|
KFMO.Skins[1] = Finalblend'KFX.StalkerGlow';
|
|
KFMO.bUnlit = true;
|
|
}
|
|
|
|
if(Instr(caps(KFMonsterST), "GHOST") != -1 && !KFMO.bSpotted)
|
|
{
|
|
KFMO.Skins[0] = Finalblend'KFX.StalkerGlow';
|
|
KFMO.Skins[1] = Finalblend'KFX.StalkerGlow';
|
|
KFMO.bUnlit = true;
|
|
}
|
|
|
|
if(Instr(caps(KFMonsterST), "BOSS") != -1 || Instr(caps(KFMonsterST), "PAT") != -1
|
|
|| Instr(caps(KFMonsterST), "HARD") != -1)
|
|
{
|
|
if(KFMO.bCloaked == true )
|
|
{
|
|
KFMO.Skins[0] = Finalblend'KFX.StalkerGlow';
|
|
KFMO.Skins[1] = Finalblend'KFX.StalkerGlow';
|
|
KFMO.bUnlit = true;
|
|
}
|
|
if(KFMO.bHidden == true) //Remove hard pat bullshit
|
|
KFMO.bHidden = false;
|
|
}
|
|
}
|
|
|
|
|
|
simulated function NetSpeedChanger() //Netspeed changer cuz lazy me
|
|
{
|
|
if (CurrentOptParams.ConsNetSpeed) //Change netspeed
|
|
{
|
|
PC.SetNetSpeed(CurrentOptParams.New_NetSpeed); //constant netspeed
|
|
return;
|
|
}
|
|
|
|
if (KFGameReplicationInfo(PC.GameReplicationInfo).TimeToNextWave > 0 || !KFGameReplicationInfo(PC.GameReplicationInfo).bWaveInProgress)
|
|
{
|
|
PC.SetNetSpeed(CurrentOptParams.nozed_NetSpeed); // same as PC.ConsoleCommand("netspeed x"), but faster
|
|
}
|
|
else if (KFGameReplicationInfo(PC.GameReplicationInfo).bWaveInProgress
|
|
|| KFGameReplicationInfo(PC.GameReplicationInfo).MaxMonsters > 0)
|
|
{
|
|
PC.SetNetSpeed(CurrentOptParams.New_NetSpeed); // same as PC.ConsoleCommand("netspeed x"), but faster
|
|
}
|
|
}
|
|
|
|
|
|
simulated function ControlRagdolls()
|
|
{
|
|
local int i;
|
|
|
|
for (i=0; i < deadZeds.length; i++)
|
|
{
|
|
if (deadZeds[i]==none) //Avoid log-spam
|
|
{
|
|
deadZeds.Remove(i,1);
|
|
continue;
|
|
}
|
|
// PC.ClientMessage(deadZeds[i].name @ deadZeds[i].lifespan @ deadZeds[i].bCollideWorld);
|
|
|
|
if (CurrentOptParams.bNoRagdolls) //Destroy ragdolls
|
|
{
|
|
if (deadZeds[i].Destroy())
|
|
deadZeds.Remove(i,1);
|
|
else
|
|
{
|
|
deadZeds[i].bDestroyNextTick = true;
|
|
deadZeds.Remove(i,1);
|
|
}
|
|
}
|
|
|
|
else if(!deadZeds[i].bCollideWorld) //set lifespan only once
|
|
{ //vanilla dead zeds don't have bCollideWorld
|
|
deadZeds[i].Lifespan = CurrentOptParams.RagdollLifeSpan;
|
|
deadZeds[i].bCollideWorld = true; //Bodies just fall through floor without that
|
|
}
|
|
}
|
|
|
|
if (DeadZeds.length > Level.MaxRagdolls) //destroying our ragdolls with lifespan cuz sometimes engine ragdoll destroying bugging out
|
|
{
|
|
for (i=0; i < DeadZeds.length - Level.MaxRagdolls; i++)
|
|
if (DeadZeds[DeadZeds.length-1].Destroy()) //Destroying last ragdolls in our array
|
|
DeadZeds.Remove(DeadZeds.length-1,1); //Removing none references
|
|
}
|
|
}
|
|
|
|
//================================Firebug shit
|
|
|
|
simulated function FirebugDisabler() //Some tweaks to burn emitters
|
|
{
|
|
local class<Emitter> E;
|
|
local int i;
|
|
|
|
if (LowGore)
|
|
{
|
|
//Some tweaks to Alt burn emitter
|
|
class'KFAltMonsterFlame'.default.Emitters[0] = class'KFBurnEffect_FPS'.default.Emitters[0];
|
|
//light
|
|
class'KFAltMonsterFlame'.default.LightRadius = LC.LightRadius;
|
|
class'KFAltMonsterFlame'.default.LightType = LC.LightType;
|
|
class'KFAltMonsterFlame'.default.LightBrightness = LC.LightBrightness;
|
|
class'KFAltMonsterFlame'.default.LightHue = LC.LightHue;
|
|
class'KFAltMonsterFlame'.default.LightSaturation = LC.LightSaturation;
|
|
class'KFAltMonsterFlame'.default.bDynamicLight = LC.bDynamicLight;
|
|
class'KFAltMonsterFlame'.default.bSpecialLit = LC.bSpecialLit;
|
|
}
|
|
|
|
if (LagEmitters.length == 0)
|
|
return;
|
|
|
|
//Lighting tweaks (from pulse to steady light cuz of fps drops when using multiple pulse lights)
|
|
for (i=0;i<LagEmitters.length;i++)
|
|
{
|
|
E = GetEmitterClassFromString(LagEmitters[i]);
|
|
if (E==none)
|
|
continue;
|
|
|
|
if (LC.LightRadius >= 0)
|
|
E.default.LightRadius = LC.LightRadius;
|
|
E.default.LightType = LC.LightType;
|
|
if (LC.LightBrightness >= 0)
|
|
E.default.LightBrightness = LC.LightBrightness;
|
|
if (LC.LightHue >= 0)
|
|
E.default.LightHue = LC.LightHue;
|
|
if (LC.LightSaturation >= 0)
|
|
E.default.LightSaturation = LC.LightSaturation;
|
|
E.default.bDynamicLight = LC.bDynamicLight;
|
|
E.default.bSpecialLit = LC.bSpecialLit;
|
|
}
|
|
|
|
// Some tweaks to Burn emitter
|
|
class'KFMonsterFlame'.default.LightRadius = LC.LightRadius;
|
|
class'KFMonsterFlame'.default.LightType = LC.LightType;
|
|
class'KFMonsterFlame'.default.LightBrightness = LC.LightBrightness;
|
|
class'KFMonsterFlame'.default.LightHue = LC.LightHue;
|
|
class'KFMonsterFlame'.default.LightSaturation = LC.LightSaturation;
|
|
class'KFMonsterFlame'.default.bDynamicLight = LC.bDynamicLight;
|
|
class'KFMonsterFlame'.default.bSpecialLit = LC.bSpecialLit;
|
|
}
|
|
|
|
|
|
//=======================================================for preloading assets hax ofc
|
|
simulated function LoadZedsAssets(byte Asset)
|
|
{
|
|
local KFMonster KFM;
|
|
local array<string> ZedClassNames;
|
|
|
|
// Standard
|
|
if (Asset == 0)
|
|
ZedClassNames = KFMonsterClassNames_Standard;
|
|
// Circus
|
|
else if (Asset == 1)
|
|
ZedClassNames = KFMonsterClassNames_Circus;
|
|
// Hillbilly
|
|
else if (Asset == 2)
|
|
ZedClassNames = KFMonsterClassNames_Halloween;
|
|
// XMAS
|
|
else if (Asset == 2)
|
|
ZedClassNames = KFMonsterClassNames_XMas;
|
|
// Custom
|
|
else if (Asset == 4)
|
|
ZedClassNames = CustomZeds;
|
|
|
|
LoadVanillaMonster(ZedClassNames);
|
|
log(">>> a_MonsterOptimizer -> LoadZedsAssets() called with asset IDX - " $ Asset);
|
|
|
|
// Kill locally spawned zeds, hehehe
|
|
forEach DynamicActors (class'KFMonster', KFM)
|
|
KFM.Suicide();
|
|
}
|
|
|
|
|
|
// TWI summon function
|
|
final private function LoadVanillaMonster(array<string> ClassNames)
|
|
{
|
|
local class<actor> NewClass;
|
|
local vector SpawnLoc;
|
|
local int i;
|
|
|
|
for (i = 0; i < ClassNames.length; i++)
|
|
{
|
|
NewClass = class<actor>(DynamicLoadObject(ClassNames[i], class'class', true));
|
|
|
|
if (NewClass != none && PC != none)
|
|
{
|
|
SpawnLoc = PC.Location;
|
|
PC.spawn(NewClass,,, SpawnLoc);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
// ======================================================= for preloading assets hax ofc end
|
|
// Simple function that copy All particle emitter inline set from source to target
|
|
// return -1 if error
|
|
// If Target has more emitters that source, emitters will be nopped if NoneFlag or left intact
|
|
simulated function int LoadAndPolluteGoreEmitters(string sourceName, string targetName, optional bool NoneFlag)
|
|
{
|
|
local class<Emitter> Source;
|
|
local class<Emitter> Target;
|
|
local int k;
|
|
|
|
Source = class<Emitter>(DynamicLoadObject(sourceName, class'class', true));
|
|
Target = class<Emitter>(DynamicLoadObject(targetName, class'class', true));
|
|
|
|
if (Source == none || Target == none)
|
|
return -1;
|
|
|
|
for (k = 0; k < Target.default.Emitters.Length; k++)
|
|
{
|
|
// if NoneFlag overwrite particle emitters with nones
|
|
if (Source.default.Emitters[k] == none && NoneFlag)
|
|
Target.default.Emitters[k] = none;
|
|
// stop on first none reference
|
|
else if (Source.default.Emitters[k] == none && !NoneFlag)
|
|
break;
|
|
|
|
Target.default.Emitters[k] = Source.default.Emitters[k];
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
// Load emitter defaults from backup classes
|
|
simulated function LoadGoreEmitters(string targetName, byte EmitterNumber)
|
|
{
|
|
local int i;
|
|
local Class<Emitter> Target;
|
|
local array<class <Emitter> > SourceArray;
|
|
|
|
if (BackupGore.length == 0 && EmitterNumber == 0)
|
|
{
|
|
BackupGore[0] = class<Emitter>(DynamicLoadObject(TWIGoreBackup[0], class'class', true));
|
|
BackupGore[1] = class<Emitter>(DynamicLoadObject(TWIGoreBackup[1], class'class', true));
|
|
BackupGore[2] = class<Emitter>(DynamicLoadObject(TWIGoreBackup[2], class'class', true));
|
|
BackupGore[3] = class<Emitter>(DynamicLoadObject(TWIGoreBackup[3], class'class', true));
|
|
}
|
|
if (OptGore.length == 0 && EmitterNumber == 1)
|
|
{
|
|
OptGore[0] = class<Emitter>(DynamicLoadObject(TWIGoreBackup[4], class'class', true));
|
|
OptGore[1] = class<Emitter>(DynamicLoadObject(TWIGoreBackup[5], class'class', true));
|
|
OptGore[2] = class<Emitter>(DynamicLoadObject(TWIGoreBackup[6], class'class', true));
|
|
OptGore[3] = class<Emitter>(DynamicLoadObject(TWIGoreBackup[7], class'class', true));
|
|
}
|
|
if (LowGoreE.length == 0 && EmitterNumber == 2)
|
|
{
|
|
LowGoreE[0] = class<Emitter>(DynamicLoadObject(TWIGoreBackup[8], class'class', true));
|
|
LowGoreE[1] = class<Emitter>(DynamicLoadObject(TWIGoreBackup[9], class'class', true));
|
|
LowGoreE[2] = class<Emitter>(DynamicLoadObject(TWIGoreBackup[10], class'class', true));
|
|
LowGoreE[3] = class<Emitter>(DynamicLoadObject(TWIGoreBackup[11], class'class', true));
|
|
}
|
|
if (NoGore.length == 0 && EmitterNumber == 3)
|
|
{
|
|
NoGore[0] = class<Emitter>(DynamicLoadObject(TWIGoreBackup[12], class'class', true));
|
|
NoGore[1] = class<Emitter>(DynamicLoadObject(TWIGoreBackup[13], class'class', true));
|
|
NoGore[2] = class<Emitter>(DynamicLoadObject(TWIGoreBackup[14], class'class', true));
|
|
NoGore[3] = class<Emitter>(DynamicLoadObject(TWIGoreBackup[15], class'class', true));
|
|
}
|
|
|
|
Target = class<Emitter>(DynamicLoadObject(targetName, class'class', true));
|
|
if (Target == none )
|
|
return;
|
|
|
|
switch (EmitterNumber)
|
|
{
|
|
case 0:
|
|
SourceArray = BackupGore;
|
|
break;
|
|
case 1:
|
|
SourceArray = OptGore;
|
|
break;
|
|
case 2:
|
|
SourceArray = LowGoreE;
|
|
break;
|
|
case 3:
|
|
SourceArray = NoGore;
|
|
break;
|
|
}
|
|
|
|
for (i = 0; i < SourceArray.length; i++)
|
|
{
|
|
if (Instr(Target, Mid(SourceArray[i],Instr(SourceArray[i], "_") + 1)) != -1)
|
|
{
|
|
LoadAndPolluteGoreEmitters(string(SourceArray[i]), string(target));
|
|
target.default.bHidden = SourceArray[i].default.bHidden;
|
|
target.default.bUnlit = SourceArray[i].default.bUnlit;
|
|
target.default.LifeSpan = SourceArray[i].default.LifeSpan;
|
|
target.default.Style = SourceArray[i].default.Style;
|
|
target.default.bDirectional = SourceArray[i].default.bDirectional;
|
|
break;
|
|
}
|
|
else
|
|
continue;
|
|
}
|
|
|
|
// unload our classes
|
|
BackupGore.length = 0;
|
|
OptGore.length = 0;
|
|
LowGoreE.length = 0;
|
|
NoGore.length = 0;
|
|
}
|
|
|
|
// Restore emitters from backup
|
|
simulated function RestoreGoreEmitterFromBackups()
|
|
{
|
|
local int i, k;
|
|
local Class<Emitter> CLEmitter;
|
|
|
|
if (EMP_back.length==0)
|
|
return;
|
|
|
|
for (i=0;i<EMP_back.length;i++)
|
|
{
|
|
CLEmitter = class<Emitter>(DynamicLoadObject(EMP_back[i].ClassName, class'class', true));
|
|
if(CLEmitter==none)
|
|
continue;
|
|
|
|
for (k=0; k < CLEmitter.default.Emitters.Length; k++)
|
|
{
|
|
CLEmitter.default.Emitters[k].Disabled = EMP_back[i].CEMP[k].Disabled;
|
|
CLEmitter.default.Emitters[k].UseCollision = EMP_back[i].CEMP[k].UseCollision;
|
|
CLEmitter.default.Emitters[k].AcceptsProjectors = EMP_back[i].CEMP[k].AcceptsProjectors;
|
|
}
|
|
}
|
|
}
|
|
|
|
//Reset flag indicates that emitter should reset to default parameters
|
|
simulated function AnotherGoreEmitterLoad(string EmitterToLoad, EMB EmitterPrefs)
|
|
{
|
|
/*
|
|
var EMP_backups EMP_backSingle; //for backuping emitters properties, single emitter
|
|
var array<EMP_backups> EMP_back; //for backuping emitters properties, emitters array
|
|
*/
|
|
local Class<Emitter> CLEmitter;
|
|
local int k;
|
|
|
|
CLEmitter = class<Emitter>(DynamicLoadObject(EmitterToLoad, class'class', true));
|
|
if(CLEmitter==none)
|
|
return;
|
|
|
|
// backuping our emitters
|
|
EMP_backSingle.ClassName = string(CLEmitter);
|
|
EMP_backSingle.bHidden = CLEmitter.default.bHidden;
|
|
EMP_backSingle.bUnlit = CLEmitter.default.bUnlit;
|
|
EMP_backSingle.Lifespan = CLEmitter.default.LifeSpan;
|
|
|
|
for(k=0; k < CLEmitter.default.Emitters.Length; k++) //Backuping particle emitters preferences
|
|
{
|
|
EMP_backSingle.CEMP[k].ClassName = string(CLEmitter.default.Emitters[k]);
|
|
EMP_backSingle.CEMP[k].Disabled = CLEmitter.default.Emitters[k].Disabled;
|
|
EMP_backSingle.CEMP[k].UseCollision = CLEmitter.default.Emitters[k].UseCollision;
|
|
EMP_backSingle.CEMP[k].AcceptsProjectors = CLEmitter.default.Emitters[k].AcceptsProjectors;
|
|
}
|
|
|
|
if(EMP_back.length !=0)
|
|
{
|
|
EMP_back.length = EMP_back.length + 1;
|
|
EMP_back[EMP_back.length] = EMP_backSingle;
|
|
}
|
|
|
|
else
|
|
EMP_back[EMP_back.length] = EMP_backSingle;
|
|
|
|
// Apply our tweaks
|
|
CLEmitter.default.bHidden = EmitterPrefs.bHidden;
|
|
CLEmitter.default.bUnlit = EmitterPrefs.bUnlit;
|
|
CLEmitter.default.LifeSpan = EmitterPrefs.Lifespan;
|
|
|
|
for(k=0; k < CLEmitter.default.Emitters.Length; k++)
|
|
{
|
|
CLEmitter.default.Emitters[k].UseCollision = EmitterPrefs.UseCollision;
|
|
ClEmitter.default.Emitters[k].Disabled = EmitterPrefs.Disabled; //Disable all particle emitters
|
|
ClEmitter.default.Emitters[k].AcceptsProjectors = EmitterPrefs.AcceptsProjectors;
|
|
}
|
|
}
|
|
//Rewrite this and make this shit dynamic
|
|
//=====================================================================
|
|
simulated function AddStandardGorePresets()
|
|
{
|
|
local int i,k;
|
|
local class<Emitter> ClEmitter;
|
|
|
|
Gore_Preset.PresetName = "OPTIMIZED_TWI";
|
|
Gore_Preset.PresetDescription = "Optimized TWI shit...";
|
|
Gore_Preset.EmittersToLoad.Insert(0, KFMonsterGibEmitters.length);
|
|
|
|
for (i=0; i< KFMonsterGibEmitters.length; i++)
|
|
{
|
|
Gore_Preset.EmittersToLoad[i].ClassName = KFMonsterGibEmitters[i];
|
|
Gore_Preset.EmittersToLoad[i].bHidden = false;
|
|
Gore_Preset.EmittersToLoad[i].bUnlit = true;
|
|
Gore_Preset.EmittersToLoad[i].LifeSpan = 5;
|
|
|
|
CLEmitter = class<Emitter>(DynamicLoadObject(KFMonsterGibEmitters[i], class'class', true));
|
|
// if (CLEmitter == none)
|
|
// PC.ClientMessage("OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO" @ KFMonsterGibEmitters[i]);
|
|
Gore_Preset.EmittersToLoad[i].CEMP.Insert(0, CLEmitter.default.Emitters.Length);
|
|
for (k=0; k < CLEmitter.default.Emitters.Length; k++) //Editing particle emitters
|
|
{
|
|
Gore_Preset.EmittersToLoad[i].CEMP[k].ClassName = string(CLEmitter.default.Emitters[k]);
|
|
Gore_Preset.EmittersToLoad[i].CEMP[k].Disabled = false;
|
|
if (int(CLEmitter.default.Emitters[k].InitialParticlesPerSecond / CLEmitter.default.Emitters[k].MaxParticles) > 350) //not fucking 0.00000001
|
|
Gore_Preset.EmittersToLoad[i].CEMP[k].InitialParticlesPerSecond = float(CLEmitter.default.Emitters[k].MaxParticles * 200); //0.01 ms to spawn
|
|
else
|
|
Gore_Preset.EmittersToLoad[i].CEMP[k].InitialParticlesPerSecond = CLEmitter.default.Emitters[k].InitialParticlesPerSecond; //else let's save old value
|
|
|
|
Gore_Preset.EmittersToLoad[i].CEMP[k].UseCollision = CLEmitter.default.Emitters[k].UseCollision;
|
|
Gore_Preset.EmittersToLoad[i].CEMP[k].AcceptsProjectors = false;
|
|
}
|
|
}
|
|
Gore_Presets[0] = Gore_Preset;
|
|
|
|
Gore_Preset.PresetName = "NO_GORE";
|
|
Gore_Preset.PresetDescription = "No gore at all. Disables all emitters.";
|
|
|
|
Gore_Preset.EmittersToLoad.Insert(0, KFMonsterGibEmitters.length);
|
|
for (i=0; i< KFMonsterGibEmitters.length; i++)
|
|
{
|
|
Gore_Preset.EmittersToLoad[i].ClassName = KFMonsterGibEmitters[i];
|
|
Gore_Preset.EmittersToLoad[i].bHidden = true;
|
|
Gore_Preset.EmittersToLoad[i].bUnlit = true;
|
|
Gore_Preset.EmittersToLoad[i].LifeSpan = 0.5;
|
|
|
|
CLEmitter = class<Emitter>(DynamicLoadObject(KFMonsterGibEmitters[i], class'class', true));
|
|
Gore_Preset.EmittersToLoad[i].CEMP.Insert(0, CLEmitter.default.Emitters.Length);
|
|
for (k=0; k < CLEmitter.default.Emitters.Length; k++) //Editing particle emitters
|
|
{
|
|
Gore_Preset.EmittersToLoad[i].CEMP[k].ClassName = string(CLEmitter.default.Emitters[k]);
|
|
Gore_Preset.EmittersToLoad[i].CEMP[k].Disabled = true;
|
|
Gore_Preset.EmittersToLoad[i].CEMP[k].UseCollision = false;
|
|
Gore_Preset.EmittersToLoad[i].CEMP[k].AcceptsProjectors = false;
|
|
}
|
|
}
|
|
Gore_Presets[1] = Gore_Preset;
|
|
|
|
Gore_Preset.PresetName = "LOW_GORE";
|
|
Gore_Preset.PresetDescription = "Low gore.";
|
|
|
|
Gore_Preset.EmittersToLoad.Insert(0, KFMonsterGibEmitters.length);
|
|
for (i=0; i< KFMonsterGibEmitters.length; i++)
|
|
{
|
|
Gore_Preset.EmittersToLoad[i].ClassName = KFMonsterGibEmitters[i];
|
|
Gore_Preset.EmittersToLoad[i].bHidden = false;
|
|
Gore_Preset.EmittersToLoad[i].bUnlit = true;
|
|
Gore_Preset.EmittersToLoad[i].LifeSpan = 5;
|
|
|
|
CLEmitter = class<Emitter>(DynamicLoadObject(KFMonsterGibEmitters[i], class'class', true));
|
|
Gore_Preset.EmittersToLoad[i].CEMP.Insert(0, CLEmitter.default.Emitters.Length);
|
|
for (k=0; k < CLEmitter.default.Emitters.Length; k++) //Editing particle emitters
|
|
{
|
|
Gore_Preset.EmittersToLoad[i].CEMP[k].ClassName = string(CLEmitter.default.Emitters[k]);
|
|
Gore_Preset.EmittersToLoad[i].CEMP[k].Disabled = false;
|
|
|
|
if (int(CLEmitter.default.Emitters[k].InitialParticlesPerSecond / CLEmitter.default.Emitters[k].MaxParticles) > 350) //not fucking 0.00000001
|
|
Gore_Preset.EmittersToLoad[i].CEMP[k].InitialParticlesPerSecond = float(CLEmitter.default.Emitters[k].MaxParticles * 200); //0.01 ms to spawn
|
|
else
|
|
Gore_Preset.EmittersToLoad[i].CEMP[k].InitialParticlesPerSecond = CLEmitter.default.Emitters[k].InitialParticlesPerSecond; //else let's save old value
|
|
|
|
Gore_Preset.EmittersToLoad[i].CEMP[k].UseCollision = false;
|
|
Gore_Preset.EmittersToLoad[i].CEMP[k].AcceptsProjectors = false;
|
|
}
|
|
}
|
|
Gore_Presets[2] = Gore_Preset;
|
|
Gore_Preset.PresetName = "TWI";
|
|
Gore_Preset.PresetDescription = "Just TWI shit...";
|
|
|
|
Gore_Preset.EmittersToLoad.Insert(0, KFMonsterGibEmitters.length);
|
|
for (i=0; i< KFMonsterGibEmitters.length; i++)
|
|
{
|
|
CLEmitter = class<Emitter>(DynamicLoadObject(KFMonsterGibEmitters[i], class'class', true));
|
|
Gore_Preset.EmittersToLoad[i].ClassName = KFMonsterGibEmitters[i];
|
|
Gore_Preset.EmittersToLoad[i].bHidden = false;
|
|
Gore_Preset.EmittersToLoad[i].bUnlit = false;
|
|
Gore_Preset.EmittersToLoad[i].LifeSpan = CLEmitter.default.Lifespan;
|
|
|
|
Gore_Preset.EmittersToLoad[i].CEMP.Insert(0, CLEmitter.default.Emitters.Length);
|
|
for (k=0; k < CLEmitter.default.Emitters.Length; k++) //Editing particle emitters
|
|
{
|
|
Gore_Preset.EmittersToLoad[i].CEMP[k].ClassName = string(CLEmitter.default.Emitters[k]);
|
|
Gore_Preset.EmittersToLoad[i].CEMP[k].Disabled = false;
|
|
Gore_Preset.EmittersToLoad[i].CEMP[k].InitialParticlesPerSecond = CLEmitter.default.Emitters[k].InitialParticlesPerSecond; //else let's save old value
|
|
|
|
Gore_Preset.EmittersToLoad[i].CEMP[k].UseCollision = CLEmitter.default.Emitters[k].UseCollision;
|
|
Gore_Preset.EmittersToLoad[i].CEMP[k].AcceptsProjectors = false;
|
|
}
|
|
}
|
|
Gore_Presets[3] = Gore_Preset;
|
|
}
|
|
|
|
|
|
simulated function ApplyStandardGorePresets(string SetPresetName)
|
|
{
|
|
local int i,k, l;
|
|
local class<Emitter> ClEmitter;
|
|
for (l=0; l < Gore_Presets.length; l++)
|
|
{
|
|
if (Gore_Presets[l].PresetName == SetPresetName)
|
|
{
|
|
Gore_Preset = Gore_Presets[l];
|
|
|
|
for (i=0; i< KFMonsterGibEmitters.length; i++)
|
|
{
|
|
if (Gore_Preset.EmittersToLoad[i].ClassName == KFMonsterGibEmitters[i])
|
|
{
|
|
|
|
CLEmitter = class<Emitter>(DynamicLoadObject(KFMonsterGibEmitters[i], class'class', true));
|
|
|
|
CLEmitter.default.bHidden = Gore_Preset.EmittersToLoad[i].bHidden;
|
|
CLEmitter.default.bUnlit = Gore_Preset.EmittersToLoad[i].bUnlit;
|
|
CLEmitter.default.LifeSpan = Gore_Preset.EmittersToLoad[i].LifeSpan;
|
|
//PC.ClientMessage("Hidden is" @ CLEmitter.default.bHidden @ "Unlit is" @ CLEmitter.default.bUnlit @ "Lifespan is" @ CLEmitter.default.LifeSpan);
|
|
|
|
for (k=0; k < CLEmitter.default.Emitters.Length; k++) //Editing particle emitters
|
|
{
|
|
CLEmitter.default.Emitters[k].Disabled = Gore_Preset.EmittersToLoad[i].CEMP[k].Disabled;
|
|
//PC.ClientMessage("Disabled is" @ Gore_Preset.EmittersToLoad[i].CEMP[k].Disabled @ "on" @ CLEmitter.default.Emitters[k]);
|
|
CLEmitter.default.Emitters[k].InitialParticlesPerSecond = Gore_Preset.EmittersToLoad[i].CEMP[k].InitialParticlesPerSecond;
|
|
//PC.ClientMessage("Initial particles are" @ Gore_Preset.EmittersToLoad[i].CEMP[k].InitialParticlesPerSecond);
|
|
CLEmitter.default.Emitters[k].UseCollision = Gore_Preset.EmittersToLoad[i].CEMP[k].UseCollision;
|
|
//PC.ClientMessage(Gore_Preset.EmittersToLoad[i].CEMP[k].UseCollision);
|
|
CLEmitter.default.Emitters[k].AcceptsProjectors = Gore_Preset.EmittersToLoad[i].CEMP[k].AcceptsProjectors;
|
|
//PC.ClientMessage(Gore_Preset.EmittersToLoad[i].CEMP[k].AcceptsProjectors);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
else
|
|
continue;
|
|
}
|
|
}
|
|
|
|
//=====================================================================
|
|
//Some gore-related emitter tweaks
|
|
simulated function OptimizeGore()
|
|
{
|
|
//local int i;
|
|
GibAndGibletsTweaks(false);
|
|
/*
|
|
if(CurrentOptParams.UserSettingsToEmitters) //load user settings
|
|
{
|
|
for (i=0; i < KFMonsterGibEmitters.length; i++)
|
|
{
|
|
AnotherGoreEmitterLoad(KFMonsterGibEmitters[i], User_EMPS); //Load user settings
|
|
}
|
|
}
|
|
*/
|
|
if(Gore_Presets.length == 0)
|
|
AddStandardGorePresets();
|
|
|
|
ApplyStandardGorePresets(CurrentOptParams.GoreLevel); //Apply our gore parameters
|
|
switch(CurrentOptParams.GoreLevel)
|
|
{
|
|
case "OPTIMIZED_TWI":
|
|
LoadGoreEmitters(TWIGibEmitters[0], 1);
|
|
LoadGoreEmitters(TWIGibEmitters[1], 1);
|
|
LoadGoreEmitters(TWIGibEmitters[2], 1);
|
|
LoadGoreEmitters(TWIGibEmitters[3], 1);
|
|
break;
|
|
case "TWI":
|
|
LoadGoreEmitters(TWIGibEmitters[0], 0);
|
|
LoadGoreEmitters(TWIGibEmitters[1], 0);
|
|
LoadGoreEmitters(TWIGibEmitters[2], 0);
|
|
LoadGoreEmitters(TWIGibEmitters[3], 0);
|
|
break;
|
|
case "NO_GORE": //No gore preset
|
|
LoadGoreEmitters(TWIGibEmitters[0], 3);
|
|
LoadGoreEmitters(TWIGibEmitters[1], 3);
|
|
LoadGoreEmitters(TWIGibEmitters[2], 3);
|
|
LoadGoreEmitters(TWIGibEmitters[3], 3);
|
|
break;
|
|
case "LOW_GORE":
|
|
LoadGoreEmitters(TWIGibEmitters[0], 2);
|
|
LoadGoreEmitters(TWIGibEmitters[1], 2);
|
|
LoadGoreEmitters(TWIGibEmitters[2], 2);
|
|
LoadGoreEmitters(TWIGibEmitters[3], 2);
|
|
break;
|
|
case "GORY!":
|
|
break;
|
|
case "BLOOD FOR THE BLOOD GOD!":
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Tweaks for gibz and giblets
|
|
// Pollute gib classes, flag reset to default parameters
|
|
simulated function PolluteGibClasses(string GibGlass,optional bool Reset)
|
|
{
|
|
local class<KFGib> KFGib;
|
|
|
|
KFGib = GetGibletsClassFromString(GibGlass);
|
|
if (KFGib==none)
|
|
return;
|
|
|
|
if (!Reset)
|
|
{
|
|
KFGib.default.bHidden = CurrentOptParams.bHideGibs;
|
|
KFGib.default.bUnlit = CurrentOptParams.bUnlitGibs;
|
|
KFGib.default.LifeSpan= CurrentOptParams.GibsLifespan;
|
|
if (CurrentOptParams.GibUseDeferRendering)
|
|
{
|
|
KFGib.default.Style = STY_Additive; //Enable defer rendering
|
|
KFGib.default.bDeferRendering = true;
|
|
}
|
|
KFGib.default.MaxLights = CurrentOptParams.GibMaxLights;
|
|
KFGib.default.bUseCollisionStaticMesh= CurrentOptParams.GibUseCollisionStaticMesh;
|
|
|
|
KFGib.default.bAcceptsProjectors = CurrentOptParams.GibAcceptProjectors;
|
|
KFGib.default.bStaticLighting = CurrentOptParams.GibStaticLighting;
|
|
}
|
|
else
|
|
{
|
|
KFGib.default.bHidden = false;
|
|
KFGib.default.bUnlit = false;
|
|
KFGib.default.LifeSpan= 6.0;
|
|
if (CurrentOptParams.GibUseDeferRendering)
|
|
{
|
|
KFGib.default.Style = STY_Normal;
|
|
}
|
|
KFGib.default.MaxLights = 4;
|
|
KFGib.default.bUseCollisionStaticMesh= true;
|
|
|
|
KFGib.default.bAcceptsProjectors = true;
|
|
KFGib.default.bStaticLighting = false;
|
|
}
|
|
}
|
|
|
|
simulated function PolluteGibletsClasses(string GibletGlass,optional bool Reset)
|
|
{
|
|
local class<SeveredAppendage> KFSevered;
|
|
|
|
KFSevered = GetGibClassFromString(GibletGlass);
|
|
if (KFSevered==none)
|
|
return;
|
|
|
|
if (!Reset)
|
|
{
|
|
KFSevered.default.bHidden = CurrentOptParams.bHideGiblets;
|
|
KFSevered.default.bUnlit = CurrentOptParams.bUnlitGiblets;
|
|
KFSevered.default.LifeSpan = CurrentOptParams.GibletsLifespan;
|
|
if (CurrentOptParams.GibletsUseDeferRendering)
|
|
{
|
|
KFSevered.default.Style = STY_Additive; //Enable defer rendering
|
|
KFSevered.default.bDeferRendering = true;
|
|
}
|
|
KFSevered.default.MaxLights = CurrentOptParams.GibletsMaxLights;
|
|
KFSevered.default.bUseCollisionStaticMesh= CurrentOptParams.GibletsUseCollisionStaticMesh;
|
|
|
|
KFSevered.default.bAcceptsProjectors = CurrentOptParams.GibletsAcceptProjectors;
|
|
KFSevered.default.bStaticLighting = CurrentOptParams.GibletsStaticLighting;
|
|
}
|
|
|
|
else
|
|
{
|
|
KFSevered.default.bHidden = false;
|
|
KFSevered.default.bUnlit = false;
|
|
KFSevered.default.LifeSpan = 8.0;
|
|
if (CurrentOptParams.GibletsUseDeferRendering)
|
|
{
|
|
KFSevered.default.Style = STY_Normal; //Disable defer rendering
|
|
KFSevered.default.bDeferRendering = true;
|
|
}
|
|
KFSevered.default.MaxLights = 4;
|
|
KFSevered.default.bUseCollisionStaticMesh= false;
|
|
|
|
KFSevered.default.bAcceptsProjectors = true;
|
|
KFSevered.default.bStaticLighting = false;
|
|
}
|
|
}
|
|
|
|
simulated function GibAndGibletsTweaks(bool Reset)
|
|
{
|
|
local int i;
|
|
|
|
if (CurrentOptParams.bAdvancedGiblets)
|
|
{
|
|
for (i=0; i<KFMonsterGibletsClassNames.length; i++)
|
|
{
|
|
PolluteGibletsClasses(KFMonsterGibletsClassNames[i], Reset);
|
|
}
|
|
}
|
|
|
|
if (CurrentOptParams.bAdvancedGibs)
|
|
{
|
|
for (i=0; i<KFMonsterGibClassNames.length; i++)
|
|
{
|
|
PolluteGibClasses(KFMonsterGibClassNames[i], Reset);
|
|
}
|
|
}
|
|
}
|
|
|
|
//Load and pollute default monster classes
|
|
simulated function LoadMonsters(string MonsterClassToLoad, optional bool Reset)
|
|
{
|
|
local class<KFMonster> KFM;
|
|
|
|
if(!Reset)
|
|
{
|
|
KFM = GetMonsterClassFromString(MonsterClassToLoad);
|
|
if(KFM==none)
|
|
return;
|
|
|
|
KFM.default.cullDistance = CurrentOptParams.ZedCullDistance;
|
|
KFM.default.bUnlit = CurrentOptParams.useUnlit;
|
|
KFM.default.AmbientGlow =CurrentOptParams.AmbientGlow;
|
|
KFM.default.SoundOcclusion = CurrentOptParams.SoundOcclusion;
|
|
KFM.default.SoundRadius = CurrentOptParams.SoundRadius;
|
|
}
|
|
|
|
else
|
|
{
|
|
KFM.default.cullDistance = 0;
|
|
KFM.default.bUnlit = false;
|
|
KFM.default.AmbientGlow = 0;
|
|
KFM.default.SoundOcclusion = Occlusion_Default;
|
|
KFM.default.SoundRadius = 300;
|
|
}
|
|
}
|
|
|
|
//Pollute default zed classes and detect gametype
|
|
simulated function PolluteDefaults(bool Reset)
|
|
{
|
|
local int i;
|
|
|
|
for(i=0; i<KFMonsterClassNames_Standard.length; i++)
|
|
{
|
|
if (CurrentOptParams.bStandard) //Loading standard classes
|
|
{
|
|
LoadMonsters(KFMonsterClassNames_Standard[i], Reset);
|
|
}
|
|
else if (CurrentOptParams.bCircus) //Loading circus classes
|
|
{
|
|
LoadMonsters(KFMonsterClassNames_Circus[i], Reset);
|
|
}
|
|
else if (CurrentOptParams.bXmas) //Loading xmas classes
|
|
{
|
|
LoadMonsters(KFMonsterClassNames_XMas[i], Reset);
|
|
}
|
|
else if (CurrentOptParams.bHillBilly) //Loading standard classes
|
|
{
|
|
LoadMonsters(KFMonsterClassNames_Halloween[i], Reset);
|
|
}
|
|
}
|
|
|
|
if(Instr(CAPS(Level.GRI.GameClass), "SCRN")!=-1) //Scrn gametype custom zeds
|
|
{
|
|
for (i=0; i<CustomZeds.length; i++)
|
|
{
|
|
LoadMonsters(CustomZeds[i], Reset);
|
|
}
|
|
}
|
|
|
|
if(Instr(CAPS(Level.GRI.GameClass), "NICE")!=-1) //NicePack.NiceGameType
|
|
{
|
|
for(i=0; i<NiceZeds.length; i++)
|
|
{
|
|
LoadMonsters(NiceZeds[i], Reset);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
//=======================================Seasoned zeds remover
|
|
simulated function RemoveSeasonedZeds()
|
|
{
|
|
/*
|
|
CurrentOptParams.bStandard
|
|
*/
|
|
if (CurrentOptParams.bCircus)
|
|
ReplaceZedsDefaults(KFMonsterClassNames_Circus, KFMonsterClassNames_Standard);
|
|
if (CurrentOptParams.bXmas)
|
|
ReplaceZedsDefaults(KFMonsterClassNames_Halloween, KFMonsterClassNames_Standard);
|
|
if (CurrentOptParams.bHillBilly)
|
|
ReplaceZedsDefaults(KFMonsterClassNames_XMas, KFMonsterClassNames_Standard);
|
|
}
|
|
|
|
//===================================Replaces zed properties sets with KFMReplace class properties sets
|
|
simulated function ReplaceZedsDefaults(array<string> KFMonsterClassNames, array<string> KFMReplace)
|
|
{
|
|
local int i,k;
|
|
local class<KFMonster> KFM, ReplaceKFM;
|
|
local string MeshName;
|
|
|
|
//OFC some bullshit first...
|
|
/*Shaders. Need to re-do this...
|
|
class'ZombieClot_HALLOWEEN'.default.ClotSkins[0] = shader'Chaos_WeaponPack_T.Clot_standard_shader';
|
|
class'ZombieClot_HALLOWEEN'.default.ClotSkins[1] = shader'Chaos_WeaponPack_T.Clot_standard_shader';
|
|
class'ZombieClot_HALLOWEEN'.default.ClotSkins[2] = shader'Chaos_WeaponPack_T.Clot_standard_shader';
|
|
class'ZombieClot_HALLOWEEN'.default.ClotSkins[3] = shader'Chaos_WeaponPack_T.Clot_standard_shader';
|
|
class'ZombieClot_HALLOWEEN'.default.ClotSkins[4] = shader'Chaos_WeaponPack_T.Clot_standard_shader';
|
|
class'ZombieClot_HALLOWEEN'.default.ClotSkins[5] = shader'Chaos_WeaponPack_T.Clot_standard_shader';
|
|
*/
|
|
if (KFMonsterClassNames.length != KFMReplace.length)
|
|
return;
|
|
|
|
class'ZombieGoreFast_CIRCUS'.default.bHeadGibbed=false; //go fuck your mouth with your circus shit
|
|
|
|
for (i=0; i<KFMonsterClassNames.length; i++)
|
|
{
|
|
KFM = GetMonsterClassFromString(KFMonsterClassNames[i]); //Get monster class to pollute
|
|
ReplaceKFM = GetMonsterClassFromString(KFMReplace[i]); //load class replacer
|
|
|
|
if (KFM == none || ReplaceKFM == none) // if none - continue
|
|
continue;
|
|
|
|
MeshName = string(ReplaceKFM.default.Mesh); //save mesh name
|
|
KFM.static.UpdateDefaultMesh(SkeletalMesh(DynamicLoadObject(MeshName, Class'SkeletalMesh', true))); //replace default skeletal mesh
|
|
|
|
for(k=0;k<KFM.default.Skins.Length;k++) //Reloading skins
|
|
{
|
|
KFM.default.Skins[k] = ReplaceKFM.default.Skins[k];
|
|
}
|
|
|
|
KFM.default.DetachedArmClass = ReplaceKFM.default.DetachedArmClass; //Reloading gore-related shit
|
|
KFM.default.DetachedLegClass = ReplaceKFM.default.DetachedLegClass;
|
|
KFM.default.DetachedHeadClass = ReplaceKFM.default.DetachedHeadClass;
|
|
KFM.default.HitSound[0] = ReplaceKFM.default.HitSound[0]; //Static arrays...
|
|
KFM.default.ChallengeSound[0] = ReplaceKFM.default.ChallengeSound[0]; //...
|
|
KFM.default.ChallengeSound[1] = ReplaceKFM.default.ChallengeSound[1];
|
|
KFM.default.ChallengeSound[2] = ReplaceKFM.default.ChallengeSound[2];
|
|
KFM.default.ChallengeSound[3] = ReplaceKFM.default.ChallengeSound[3];
|
|
KFM.default.AmbientSound = ReplaceKFM.default.AmbientSound; //Replacing ambient sounds
|
|
KFM.default.MoanVoice = ReplaceKFM.default.MoanVoice; //Replacing moan voice aka idle moaning sounds
|
|
KFM.default.DeathSound[0]=ReplaceKFM.default.DeathSound[0]; //...
|
|
KFM.default.DeathSound[1]=ReplaceKFM.default.DeathSound[1];
|
|
KFM.default.JumpSound=ReplaceKFM.default.JumpSound;
|
|
KFM.default.MeleeAttackHitSound=ReplaceKFM.default.MeleeAttackHitSound;
|
|
}
|
|
}
|
|
|
|
simulated function RestoreSeasonedZeds(){}
|
|
|
|
// Detect headless zeds for LowGore decaps
|
|
simulated function DetectHeadless()
|
|
{
|
|
local int i;
|
|
local KFMonster KFM;
|
|
|
|
NewTicks=0;
|
|
if (!LowGore)
|
|
return;
|
|
|
|
for (i = 0; i < cachedZeds.length; i++)
|
|
{
|
|
KFM = cachedZeds[i];
|
|
if (KFM == none)
|
|
continue;
|
|
if ((KFM.bDecapitated && KFM.Health <= 0) || KFM.bDecapitated)
|
|
{
|
|
// CuteDecapFX undone
|
|
KFM.NeckRot.Yaw = 0;
|
|
KFM.NeckRot.Roll = 0;
|
|
KFM.NeckRot.Pitch = 0;
|
|
KFM.SetBoneRotation('neck', KFM.NeckRot);
|
|
// Using decap function for melee weapons cuz no fps drops.
|
|
KFM.SpecialHideHead();
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
//==============String to class conversion
|
|
simulated function class<KFGib> GetGibletsClassFromString(string String)
|
|
{
|
|
//for conversion from string to class reference
|
|
return class<KFGib>(DynamicLoadObject(String, class'class', true));
|
|
}
|
|
|
|
simulated function class<SeveredAppendage> GetGibClassFromString(string String)
|
|
{
|
|
//for conversion from string to class reference
|
|
return class<SeveredAppendage>(DynamicLoadObject(String, class'class', true));
|
|
}
|
|
|
|
simulated function class<KFMonster> GetMonsterClassFromString(string String)
|
|
{
|
|
//for conversion from string to class reference
|
|
return class<KFMonster>(DynamicLoadObject(String, class'class', true));
|
|
}
|
|
|
|
//==============String to class conversion
|
|
simulated function class<Emitter> GetEmitterClassFromString(string String)
|
|
{
|
|
//for conversion from string to class reference
|
|
return class<Emitter>(DynamicLoadObject(String, class'class', true));
|
|
}
|
|
|
|
|
|
// self cleanup
|
|
function Termination()
|
|
{
|
|
pc = none;
|
|
cachedZeds.length = 0;
|
|
deadZeds.length = 0;
|
|
ZoneInfos.length = 0;
|
|
Zone = none;
|
|
CurrentOptParams = none;
|
|
LC = none;
|
|
EMP_backSingle = none;
|
|
EMP_back.length = 0;
|
|
User_EMPS = none;
|
|
Gore_Presets.length = 0;
|
|
Gore_Preset = none;
|
|
BackupGore.length = 0;
|
|
OptGore.length = 0;
|
|
LowGoreE.length = 0;
|
|
NoGore.length = 0;
|
|
|
|
super.Termination();
|
|
}
|
|
|
|
defaultproperties
|
|
{
|
|
bUnlit=True
|
|
}
|