Reduced the screen tint of the Damage Amplifier. More tweaks to the DOOMTEST enhancer, now it looks very pretty.
1381 lines
35 KiB
Text
1381 lines
35 KiB
Text
Class UTPlayer : DoomPlayer
|
|
{
|
|
bool lastground;
|
|
double lastvelz, prevvelz;
|
|
transient CVar footsteps, utmovement, doomspeed, doomaircontrol, nowalkdrop;
|
|
Vector2 acceleration;
|
|
Vector3 acceleration3;
|
|
int last_fm, last_sm;
|
|
int last_fm_tap, last_sm_tap;
|
|
int last_tap_fm, last_tap_sm;
|
|
int last_jump_held;
|
|
|
|
const groundspeed = 400.;
|
|
const accelrate = 2048.;
|
|
const walkfactor = 0.3;
|
|
const utaircontrol = 0.35;
|
|
const groundspeed_doomish = 600.;
|
|
const fluidfriction = 1.2;
|
|
const terminalvelocity = 2500.;
|
|
|
|
Default
|
|
{
|
|
Player.StartItem "Enforcer";
|
|
Player.StartItem "ImpactHammer";
|
|
Player.StartItem "MiniAmmo", 30;
|
|
Player.DamageScreenColor "FF 00 00";
|
|
Player.ViewHeight 46;
|
|
Player.GruntSpeed 20;
|
|
}
|
|
|
|
// Have to modify the give cheat to handle UT armor
|
|
override void CheatGive( String name, int amount )
|
|
{
|
|
if ( PlayerNumber() != consoleplayer )
|
|
A_Log(String.Format("%s is a cheater: give %s\n",player.GetUserName(),name));
|
|
if ( !player.mo || (player.health <= 0) ) return;
|
|
int giveall = ALL_NO;
|
|
if ( name ~== "all" ) giveall = ALL_YES;
|
|
else if (name ~== "everything") giveall = ALL_YESYES;
|
|
if ( name ~== "health" )
|
|
{
|
|
if ( amount > 0 )
|
|
{
|
|
health += amount;
|
|
player.health = health;
|
|
}
|
|
else player.health = health = GetMaxHealth(true);
|
|
}
|
|
if ( giveall || (name ~== "backpack") )
|
|
{
|
|
// Select the correct type of backpack based on the game
|
|
let type = (class<Inventory>)(gameinfo.backpacktype);
|
|
if ( type ) GiveInventory(type,1,true);
|
|
if ( !giveall ) return;
|
|
}
|
|
if ( giveall || (name ~== "ammo") )
|
|
{
|
|
// Find every unique type of ammo. Give it to the player if
|
|
// he doesn't have it already, and set each to its maximum.
|
|
for ( int i=0; i<AllActorClasses.Size(); i++ )
|
|
{
|
|
let type = (class<Ammo>)(AllActorClasses[i]);
|
|
if ( !type || (type.GetParentClass() != "Ammo") )
|
|
continue;
|
|
// Only give if it's for a valid weapon, unless using "give everything"
|
|
bool isvalid = false;
|
|
for ( int j=0; j<AllActorClasses.Size(); j++ )
|
|
{
|
|
let type2 = (class<Weapon>)(AllActorClasses[j]);
|
|
if ( !type2 ) continue;
|
|
let rep = GetReplacement(type2);
|
|
if ( (rep != type2) && !(rep is "DehackedPickup") ) continue;
|
|
readonly<Weapon> weap = GetDefaultByType(type2);
|
|
if ( !player.weapons.LocateWeapon(type2) || (weap.bCheatNotWeapon && (giveall != ALL_YESYES)) ) continue;
|
|
if ( (weap.AmmoType1 == type) || (weap.AmmoType2 == type) )
|
|
{
|
|
isvalid = true;
|
|
break;
|
|
}
|
|
}
|
|
if ( !isvalid ) continue;
|
|
let ammoitem = FindInventory(type);
|
|
if ( !ammoitem )
|
|
{
|
|
ammoitem = Inventory(Spawn(type));
|
|
ammoitem.AttachToOwner(self);
|
|
ammoitem.Amount = ammoitem.MaxAmount;
|
|
}
|
|
else if ( ammoitem.Amount < ammoitem.MaxAmount )
|
|
ammoitem.Amount = ammoitem.MaxAmount;
|
|
}
|
|
if ( !giveall ) return;
|
|
}
|
|
if ( giveall || (name ~== "armor") )
|
|
{
|
|
// Doom Tournament just gives the player a shield belt and maximum bonuses
|
|
let belt = Inventory(Spawn("UTShieldBelt"));
|
|
if ( !belt.CallTryPickup(self) ) belt.Destroy();
|
|
let bonus = Inventory(Spawn("UTArmorBonus"));
|
|
bonus.Amount = bonus.MaxAmount;
|
|
if ( !bonus.CallTryPickup(self) ) bonus.Destroy();
|
|
level.total_items -= 2; // spawning them in raises item count
|
|
if ( !giveall ) return;
|
|
}
|
|
if ( giveall || (name ~== "keys") )
|
|
{
|
|
for ( int i=0; i<AllActorClasses.Size(); i++ )
|
|
{
|
|
if ( !(AllActorClasses[i] is "Key") ) continue;
|
|
let keyitem = GetDefaultByType(AllActorClasses[i]);
|
|
if ( keyitem.special1 )
|
|
{
|
|
let item = Inventory(Spawn(AllActorClasses[i]));
|
|
if ( !item.CallTryPickup(self) ) item.Destroy();
|
|
}
|
|
}
|
|
if ( !giveall ) return;
|
|
}
|
|
if ( giveall || (name ~== "weapons") )
|
|
{
|
|
let savedpending = player.PendingWeapon;
|
|
for ( int i=0; i<AllActorClasses.Size(); i++ )
|
|
{
|
|
let type = (class<Weapon>)(AllActorClasses[i]);
|
|
if ( !type || (type == "Weapon") ) continue;
|
|
// Don't give replaced weapons unless the replacement was done by Dehacked.
|
|
let rep = GetReplacement(type);
|
|
if ( (rep == type) || (rep is "DehackedPickup") )
|
|
{
|
|
// Give the weapon only if it is set in a weapon slot.
|
|
if ( !player.weapons.LocateWeapon(type) ) continue;
|
|
readonly<Weapon> def = GetDefaultByType(type);
|
|
if ( (giveall == ALL_YESYES) || !def.bCheatNotWeapon )
|
|
GiveInventory(type,1,true);
|
|
}
|
|
}
|
|
player.PendingWeapon = savedpending;
|
|
if ( !giveall ) return;
|
|
}
|
|
if ( giveall || (name ~== "artifacts") )
|
|
{
|
|
for ( int i=0; i<AllActorClasses.Size(); i++ )
|
|
{
|
|
let type = (class<Inventory>)(AllActorClasses[i]);
|
|
if ( !type ) continue;
|
|
let def = GetDefaultByType (type);
|
|
if ( def.Icon.isValid() && (def.MaxAmount > 1) &&
|
|
!(type is "PuzzleItem") && !(type is "Powerup") && !(type is "Ammo") && !(type is "Armor"))
|
|
{
|
|
// Do not give replaced items unless using "give everything"
|
|
if ( (giveall == ALL_YESYES) || (GetReplacement(type) == type) )
|
|
GiveInventory(type,(amount<=0)?def.MaxAmount:amount,true);
|
|
}
|
|
}
|
|
if ( !giveall ) return;
|
|
}
|
|
if ( giveall || (name ~== "puzzlepieces") )
|
|
{
|
|
for ( int i=0; i<AllActorClasses.Size(); i++ )
|
|
{
|
|
let type = (class<PuzzleItem>)(AllActorClasses[i]);
|
|
if ( !type ) continue;
|
|
let def = GetDefaultByType(type);
|
|
if ( !def.Icon.isValid() ) continue;
|
|
// Do not give replaced items unless using "give everything"
|
|
if ( (giveall == ALL_YESYES) || (GetReplacement(type) == type) )
|
|
GiveInventory(type,(amount<=0)?def.MaxAmount:amount,true);
|
|
}
|
|
if ( !giveall ) return;
|
|
}
|
|
if ( giveall ) return;
|
|
let type = name;
|
|
if ( !type )
|
|
{
|
|
if ( PlayerNumber() == consoleplayer )
|
|
A_Log(String.Format("Unknown item \"%s\"\n",name));
|
|
}
|
|
else GiveInventory(type,amount,true);
|
|
}
|
|
|
|
override void Tick()
|
|
{
|
|
Super.Tick();
|
|
if ( !player ) return;
|
|
if ( !footsteps ) footsteps = CVar.GetCVar('flak_footsteps',players[consoleplayer]);
|
|
if ( !footsteps.GetBool() ) return;
|
|
double ang = level.time/(20*TICRATE/35.)*360.;
|
|
bool forcefootstep = false;
|
|
if ( player.onground && !bNoGravity && !lastground && (waterlevel < 3) )
|
|
{
|
|
player.jumptics = 0;
|
|
if ( lastvelz < -4 )
|
|
{
|
|
double vol = clamp((-lastvelz-4)*0.05,0.01,1.0);
|
|
if ( ((waterlevel > 0) || GetFloorTerrain().IsLiquid) && !bOnMobj ) A_PlaySound("ut/wetsplash",CHAN_AUTO,vol);
|
|
else A_PlaySound("*uland",CHAN_AUTO,vol);
|
|
}
|
|
else forcefootstep = true;
|
|
}
|
|
if ( forcefootstep || ((abs(sin(ang)) >= 1.0) && player.onground && (player.cmd.forwardmove || player.cmd.sidemove) && (waterlevel < 3)) )
|
|
{
|
|
double vol = abs(vel.xy.length())*0.03;
|
|
if ( forcefootstep ) vol = clamp(-lastvelz*0.05,0.01,1.0);
|
|
if ( (waterlevel > 0) || GetFloorTerrain().IsLiquid && !bOnMobj ) A_PlaySound("ut/playerfootstepwet",CHAN_5,vol);
|
|
else A_PlaySound("ut/playerfootstep",CHAN_5,vol);
|
|
}
|
|
lastground = player.onground;
|
|
lastvelz = prevvelz;
|
|
prevvelz = vel.z;
|
|
}
|
|
|
|
double FrictionToUnreal()
|
|
{
|
|
double fin = GetFriction();
|
|
if ( fin >= 1.0 ) return 0.0;
|
|
return 734.2969*fin*fin-1485.0868*fin+750.7899;
|
|
}
|
|
|
|
override void MovePlayer()
|
|
{
|
|
if ( !utmovement ) utmovement = CVar.GetCVar('flak_utmovement');
|
|
if ( !doomspeed ) doomspeed = CVar.GetCVar('flak_doomspeed');
|
|
if ( !doomaircontrol ) doomaircontrol = CVar.GetCVar('flak_doomaircontrol');
|
|
if ( !nowalkdrop ) nowalkdrop = CVar.GetCVar('flak_nowalkdrop');
|
|
bNODROPOFF = false;
|
|
if ( !utmovement.GetBool() )
|
|
{
|
|
Super.MovePlayer();
|
|
return;
|
|
}
|
|
UserCmd cmd = player.cmd;
|
|
if ( player.turnticks )
|
|
{
|
|
player.turnticks--;
|
|
Angle += (180./TURN180_TICKS);
|
|
}
|
|
else Angle += cmd.yaw*(360./65536.);
|
|
player.onground = (pos.z <= floorz) || bOnMobj || bMBFBouncer || (player.cheats & CF_NOCLIP2);
|
|
double friction = FrictionToUnreal();
|
|
double fs = TweakSpeeds(1.0,0.0);
|
|
if ( !doomspeed.GetBool() )
|
|
{
|
|
if ( cmd.buttons&BT_SPEED ) fs *= walkfactor;
|
|
}
|
|
else fs *= max(abs(cmd.forwardmove/12800.),abs(cmd.sidemove/10240.));
|
|
if ( CanCrouch() && (player.crouchfactor != -1) ) fs *= player.crouchfactor;
|
|
acceleration = rotatevector((cmd.forwardmove,-cmd.sidemove),angle);
|
|
Vector2 dodge = (0,0);
|
|
int fm = cmd.forwardmove;
|
|
int sm = cmd.sidemove;
|
|
if ( fm )
|
|
{
|
|
int clk = abs(gametic-last_fm_tap);
|
|
if ( (clk < 8) && (last_fm*fm == 0) && (last_tap_fm*fm>0) )
|
|
dodge += RotateVector((fm,0),angle).unit();
|
|
if ( !last_fm && (last_jump_held < gametic-1) )
|
|
{
|
|
last_fm_tap = gametic;
|
|
last_tap_fm = fm;
|
|
}
|
|
}
|
|
last_fm = fm;
|
|
if ( sm )
|
|
{
|
|
int clk = abs(gametic-last_sm_tap);
|
|
if ( (clk < 8) && (last_sm*sm == 0) && (last_tap_sm*sm>0) )
|
|
dodge += RotateVector((0,-sm),angle).unit();
|
|
if ( !last_sm && (last_jump_held < gametic-1) )
|
|
{
|
|
last_sm_tap = gametic;
|
|
last_tap_sm = sm;
|
|
}
|
|
}
|
|
last_sm = sm;
|
|
if ( !bNoGravity && player.onground )
|
|
{
|
|
if ( !waterlevel && (dodge.length() > 0) )
|
|
{
|
|
if ( doomspeed.GetBool() ) vel += dodge.unit()*(groundspeed_doomish*1.5)/TICRATE;
|
|
else vel += dodge.unit()*(groundspeed*1.5)/TICRATE;
|
|
vel.z += jumpz*0.5;
|
|
bOnMobj = false;
|
|
if ( !(player.cheats&CF_PREDICTING) )
|
|
A_PlaySound("*jump",CHAN_BODY);
|
|
if ( player.cheats & CF_REVERTPLEASE )
|
|
{
|
|
player.cheats &= ~CF_REVERTPLEASE;
|
|
player.camera = player.mo;
|
|
}
|
|
player.vel *= 0;
|
|
}
|
|
else
|
|
{
|
|
if ( nowalkdrop.GetBool() )
|
|
bNODROPOFF = ((acceleration.length() > double.epsilon) && (cmd.buttons&BT_SPEED));
|
|
// Hook in Unreal physics
|
|
Vector2 dir = (0,0);
|
|
if ( vel.xy.length() > double.epsilon ) dir = vel.xy.unit();
|
|
if ( acceleration.length() <= double.epsilon )
|
|
{
|
|
Vector2 oldvel = vel.xy;
|
|
vel.xy = vel.xy - (2 * dir) * vel.xy.length() * friction/TICRATE;
|
|
if ( oldvel dot vel.xy < 0.0 ) vel.xy *= 0;
|
|
}
|
|
else
|
|
{
|
|
Vector2 acceldir = acceleration.unit();
|
|
acceleration = acceldir * Min(acceleration.length(), accelrate/TICRATE);
|
|
vel.xy = vel.xy - (dir - acceldir) * vel.xy.length() * friction/TICRATE;
|
|
}
|
|
vel.xy = vel.xy + acceleration/TICRATE;
|
|
double maxvel;
|
|
if ( doomspeed.GetBool() ) maxvel = (groundspeed_doomish*fs)/TICRATE;
|
|
else maxvel = (groundspeed*fs)/TICRATE;
|
|
double doomfriction = clamp(GetFriction()/ORIG_FRICTION,0.0,1.0);
|
|
maxvel *= doomfriction;
|
|
if ( vel.xy.length() > maxvel ) vel.xy = vel.xy.unit()*maxvel;
|
|
if ( !(player.cheats & CF_PREDICTING) )
|
|
{
|
|
if ( acceleration.length() <= double.epsilon ) PlayIdle();
|
|
else PlayRunning();
|
|
}
|
|
player.vel = vel.xy;
|
|
}
|
|
}
|
|
else if ( !bNoGravity && !waterlevel )
|
|
{
|
|
// air acceleration when falling
|
|
float maxaccel = accelrate/TICRATE;
|
|
if ( vel.xy.length() < (40./TICRATE) )
|
|
maxaccel += (40.-vel.xy.length())/TICRATE;
|
|
if ( acceleration.length() > maxaccel )
|
|
acceleration = acceleration.unit()*maxaccel;
|
|
Vector2 dir = (0,0);
|
|
if ( vel.xy.length() > double.epsilon ) dir = vel.xy.unit();
|
|
if ( acceleration.length() <= double.epsilon )
|
|
{
|
|
Vector2 oldvel = vel.xy;
|
|
vel.xy = vel.xy - (2 * dir) * vel.xy.length() * fluidfriction/TICRATE;
|
|
if ( oldvel dot vel.xy < 0.0 ) vel.xy *= 0;
|
|
}
|
|
else
|
|
{
|
|
Vector2 acceldir = acceleration.unit();
|
|
acceleration = acceldir * Min(acceleration.length(), accelrate/TICRATE);
|
|
vel.xy = vel.xy - (dir - acceldir) * vel.xy.length() * fluidfriction/TICRATE;
|
|
}
|
|
acceleration *= doomaircontrol.GetBool()?level.aircontrol:utaircontrol;
|
|
vel.xy = vel.xy + acceleration/TICRATE;
|
|
if ( vel.length() > terminalvelocity/TICRATE ) vel = vel.unit()*(terminalvelocity/TICRATE);
|
|
player.vel *= 0;
|
|
}
|
|
else
|
|
{
|
|
// swimming uses standard physics, otherwise things break
|
|
double forwardmove, sidemove;
|
|
double bobfactor;
|
|
double friction, movefactor;
|
|
double fm, sm;
|
|
[friction, movefactor] = GetFriction();
|
|
bobfactor = (friction<ORIG_FRICTION)?movefactor:ORIG_FRICTION_FACTOR;
|
|
fm = cmd.forwardmove;
|
|
sm = cmd.sidemove;
|
|
[fm, sm] = TweakSpeeds(fm,sm);
|
|
fm *= Speed/256;
|
|
sm *= Speed/256;
|
|
if ( CanCrouch() && (player.crouchfactor != 1) )
|
|
{
|
|
fm *= player.crouchfactor;
|
|
sm *= player.crouchfactor;
|
|
bobfactor *= player.crouchfactor;
|
|
}
|
|
forwardmove = fm*movefactor*(35/TICRATE);
|
|
sidemove = sm*movefactor*(35/TICRATE);
|
|
if ( forwardmove )
|
|
{
|
|
Bob(Angle, cmd.forwardmove*bobfactor/256.,true);
|
|
ForwardThrust(forwardmove,Angle);
|
|
}
|
|
if ( sidemove )
|
|
{
|
|
let a = Angle-90;
|
|
Bob(a,cmd.sidemove*bobfactor/256.,false);
|
|
Thrust(sidemove,a);
|
|
}
|
|
if ( !(player.cheats&CF_PREDICTING) && ((forwardmove != 0) || (sidemove != 0)) )
|
|
PlayRunning();
|
|
}
|
|
if ( player.cheats & CF_REVERTPLEASE )
|
|
{
|
|
player.cheats &= ~CF_REVERTPLEASE;
|
|
player.camera = player.mo;
|
|
}
|
|
}
|
|
override void CheckJump()
|
|
{
|
|
if ( !utmovement ) utmovement = CVar.GetCVar('flak_utmovement');
|
|
if ( !utmovement.GetBool() )
|
|
{
|
|
Super.CheckJump();
|
|
return;
|
|
}
|
|
if ( player.cmd.buttons&BT_JUMP )
|
|
{
|
|
if ( player.crouchoffset ) player.crouching = 1;
|
|
else if ( waterlevel >= 2 ) Vel.z = 4*Speed;
|
|
else if ( bNoGravity ) Vel.z = 3.;
|
|
else if ( level.IsJumpingAllowed() && player.onground && (player.jumpTics == 0) && (last_jump_held < gametic-1) )
|
|
{
|
|
double jumpvelz = JumpZ;
|
|
double jumpfac = 0;
|
|
for ( let p = Inv; p != null; p = p.Inv )
|
|
{
|
|
let pp = PowerHighJump(p);
|
|
if ( !pp ) continue;
|
|
double f = pp.Strength;
|
|
if ( f > jumpfac ) jumpfac = f;
|
|
}
|
|
if ( jumpfac > 0 ) jumpvelz *= jumpfac;
|
|
Vel.z += jumpvelz;
|
|
bOnMobj = false;
|
|
player.jumpTics = -1;
|
|
if ( !(player.cheats&CF_PREDICTING) )
|
|
A_PlaySound("*jump",CHAN_BODY);
|
|
}
|
|
last_jump_held = gametic;
|
|
}
|
|
if ( !player.onground || player.jumptics )
|
|
last_jump_held = gametic;
|
|
}
|
|
}
|
|
|
|
// Random Spawner that passes through dropped status to items
|
|
Class RandomSpawner2 : RandomSpawner
|
|
{
|
|
override void PostSpawn( Actor spawned )
|
|
{
|
|
if ( !bDROPPED ) return;
|
|
if ( spawned is 'Inventory' ) Inventory(spawned).bTOSSED = bDROPPED;
|
|
if ( spawned is 'UTWeapon' )
|
|
{
|
|
spawned.SetState(spawned.ResolveState("Spawn")+1);
|
|
Inventory(spawned).bALWAYSPICKUP = true;
|
|
if ( UTWeapon(spawned).DropAmmo > 0 )
|
|
Weapon(spawned).AmmoGive1 = min(UTWeapon(spawned).DropAmmo,Weapon(spawned).AmmoGive1);
|
|
}
|
|
}
|
|
}
|
|
|
|
Class UTWeapon : Weapon
|
|
{
|
|
int DropAmmo;
|
|
bool bExtraPickup;
|
|
|
|
Property DropAmmo: DropAmmo;
|
|
|
|
// Drawstuffs under HUD
|
|
virtual ui void PreRender( double lbottom ) {}
|
|
// Drawstuffs over HUD
|
|
virtual ui void PostRender( double lbottom ) {}
|
|
|
|
override Inventory CreateTossable( int amt )
|
|
{
|
|
if ( Ammo1 && (Ammo1.Amount <= 0) ) return null;
|
|
Inventory d = Super.CreateTossable(amt);
|
|
if ( d && (d.GetClass() == GetClass()) )
|
|
{
|
|
d.SetState(d.ResolveState("Spawn")+1);
|
|
d.bALWAYSPICKUP = true;
|
|
}
|
|
return d;
|
|
}
|
|
|
|
override bool SpecialDropAction( Actor dropper )
|
|
{
|
|
SetState(ResolveState("Spawn")+1);
|
|
bALWAYSPICKUP = true;
|
|
return false;
|
|
}
|
|
|
|
override void Tick()
|
|
{
|
|
Super.Tick();
|
|
if ( !Owner || !Owner.player || (Owner.player.ReadyWeapon != self) ) return;
|
|
Owner.player.WeaponState |= WF_WEAPONBOBBING; // UT weapons always bob
|
|
}
|
|
|
|
void FireEffect()
|
|
{
|
|
let amp = DamageAmplifier(Owner.FindInventory("DamageAmplifier",true));
|
|
if ( amp ) amp.FireEffect();
|
|
}
|
|
|
|
override void OwnerDied()
|
|
{
|
|
Super.OwnerDied();
|
|
A_ClearRefire();
|
|
}
|
|
|
|
override bool HandlePickup( Inventory item )
|
|
{
|
|
if (item.GetClass() == GetClass())
|
|
{
|
|
if ( Weapon(item).PickupForAmmo(self) )
|
|
item.bPickupGood = true;
|
|
if ( (MaxAmount > 1) || bALWAYSPICKUP )
|
|
return Inventory.HandlePickup(item);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
override bool ShouldStay()
|
|
{
|
|
if ( ((multiplayer && (!deathmatch && !alwaysapplydmflags)) || sv_weaponstay) && !bDropped )
|
|
return (!bExtraPickup && !bALWAYSPICKUP);
|
|
return false;
|
|
}
|
|
override bool TryPickup( in out Actor toucher )
|
|
{
|
|
if ( !bExtraPickup ) bExtraPickup = ((MaxAmount > 1) && (toucher.CountInv(GetClass()) < MaxAmount));
|
|
return Super.TryPickup(toucher);
|
|
}
|
|
|
|
// Whole chain of function rewrites because of some stupid hardcoded deathmatch ammo multiplier
|
|
override bool TryPickupRestricted( in out Actor toucher )
|
|
{
|
|
if ( ShouldStay() ) return false;
|
|
bExtraPickup = false;
|
|
bool gaveSome = !!(NonIdioticAddAmmo(toucher,AmmoType1,AmmoGive1));
|
|
gaveSome |= !!(NonIdioticAddAmmo(toucher,AmmoType2,AmmoGive2));
|
|
if ( gaveSome ) GoAwayAndDie();
|
|
return gaveSome;
|
|
}
|
|
override void AttachToOwner( Actor other )
|
|
{
|
|
bExtraPickup = false;
|
|
Inventory.AttachToOwner(other);
|
|
Ammo1 = NonIdioticAddAmmo(Owner,AmmoType1,AmmoGive1);
|
|
Ammo2 = NonIdioticAddAmmo(Owner,AmmoType2,AmmoGive2);
|
|
SisterWeapon = AddWeapon(SisterWeaponType);
|
|
if ( Owner.player )
|
|
{
|
|
if ( !Owner.player.GetNeverSwitch() && !bNo_Auto_Switch )
|
|
Owner.player.PendingWeapon = self;
|
|
if ( Owner.player.mo == players[consoleplayer].camera )
|
|
StatusBar.ReceivedWeapon(self);
|
|
}
|
|
GivenAsMorphWeapon = false;
|
|
}
|
|
|
|
// rewrite of AddAmmo without stupid hardcoded 2.5x ammo multiplier
|
|
protected Ammo NonIdioticAddAmmo( Actor other, Class<Ammo> ammotype, int amount )
|
|
{
|
|
if ( !ammotype ) return null;
|
|
Ammo ammoitem;
|
|
if ( !bIgnoreSkill ) amount = int(amount*G_SkillPropertyFloat(SKILLP_AmmoFactor));
|
|
ammoitem = Ammo(other.FindInventory(ammotype));
|
|
if ( !ammoitem )
|
|
{
|
|
ammoitem = Ammo(Spawn(ammotype));
|
|
ammoitem.Amount = min(amount,ammoitem.MaxAmount);
|
|
ammoitem.AttachToOwner(other);
|
|
}
|
|
else if ( ammoitem.Amount < ammoitem.MaxAmount )
|
|
{
|
|
ammoitem.Amount += amount;
|
|
if ( ammoitem.Amount > ammoitem.MaxAmount )
|
|
ammoitem.Amount = ammoitem.MaxAmount;
|
|
}
|
|
return ammoitem;
|
|
}
|
|
|
|
Default
|
|
{
|
|
Weapon.BobStyle "Smooth";
|
|
Weapon.BobSpeed 1.5;
|
|
Weapon.BobRangeX 0.2;
|
|
Weapon.BobRangeY 0.4;
|
|
Weapon.YAdjust 0;
|
|
+WEAPON.NOALERT;
|
|
}
|
|
}
|
|
|
|
Class UTTeleportLight : DynamicLight
|
|
{
|
|
Default
|
|
{
|
|
DynamicLight.Type "Point";
|
|
Args 128,160,255,80;
|
|
}
|
|
override void Tick()
|
|
{
|
|
Super.Tick();
|
|
if ( alpha <= 0 )
|
|
{
|
|
Destroy();
|
|
return;
|
|
}
|
|
args[LIGHT_RED] = int(128*alpha);
|
|
args[LIGHT_GREEN] = int(160*alpha);
|
|
args[LIGHT_BLUE] = int(255*alpha);
|
|
args[LIGHT_INTENSITY] = Random[Tele](10,14)*8;
|
|
alpha -= 1./35;
|
|
}
|
|
}
|
|
|
|
Class UTItemLight : DynamicLight
|
|
{
|
|
Default
|
|
{
|
|
DynamicLight.Type "Point";
|
|
Args 255,224,160,48;
|
|
}
|
|
override void Tick()
|
|
{
|
|
Super.Tick();
|
|
if ( alpha <= 0 )
|
|
{
|
|
Destroy();
|
|
return;
|
|
}
|
|
args[LIGHT_RED] = int(255*alpha);
|
|
args[LIGHT_GREEN] = int(224*alpha);
|
|
args[LIGHT_BLUE] = int(160*alpha);
|
|
args[LIGHT_INTENSITY] = Random[Tele](6,8)*8;
|
|
alpha -= 3./35;
|
|
}
|
|
}
|
|
|
|
Class UTTeleportFog : Actor replaces TeleportFog
|
|
{
|
|
Default
|
|
{
|
|
+NOBLOCKMAP;
|
|
+NOTELEPORT;
|
|
+NOGRAVITY;
|
|
RenderStyle "Add";
|
|
}
|
|
override void PostBeginPlay()
|
|
{
|
|
Super.PostBeginPlay();
|
|
Spawn("UTTeleportLight",pos+(0,0,16));
|
|
A_PlaySound ("misc/teleport");
|
|
}
|
|
States
|
|
{
|
|
Spawn:
|
|
TELE ABCDEFGHIJKLMNOPQRSTUVWXYZ 1 Bright A_FadeOut(1./35);
|
|
TEL2 ABCDEFGHI 1 Bright A_FadeOut(1./35);
|
|
Stop;
|
|
}
|
|
}
|
|
|
|
Class UTItemFog : Actor replaces ItemFog
|
|
{
|
|
Default
|
|
{
|
|
+NOBLOCKMAP;
|
|
+NOTELEPORT;
|
|
+NOGRAVITY;
|
|
RenderStyle "Add";
|
|
}
|
|
override void PostBeginPlay()
|
|
{
|
|
Super.PostBeginPlay();
|
|
Spawn("UTItemLight",pos+(0,0,16));
|
|
}
|
|
States
|
|
{
|
|
Spawn:
|
|
TNT1 A 1;
|
|
Stop;
|
|
}
|
|
}
|
|
|
|
Class UTSpark : Actor
|
|
{
|
|
Default
|
|
{
|
|
RenderStyle "Add";
|
|
Radius 2;
|
|
Height 2;
|
|
+NOBLOCKMAP;
|
|
+FORCEXYBILLBOARD;
|
|
+MISSILE;
|
|
+MOVEWITHSECTOR;
|
|
+THRUACTORS;
|
|
+NOTELEPORT;
|
|
+DONTSPLASH;
|
|
BounceType "Doom";
|
|
BounceFactor 0.4;
|
|
Gravity 0.5;
|
|
Scale 0.05;
|
|
}
|
|
override void Tick()
|
|
{
|
|
Super.Tick();
|
|
if ( waterlevel > 0 )
|
|
{
|
|
let b = Spawn("UTBubble",pos);
|
|
b.vel = vel;
|
|
b.scale *= 0.3;
|
|
Destroy();
|
|
}
|
|
}
|
|
States
|
|
{
|
|
Spawn:
|
|
SPRK A 1 Bright A_FadeOut(0.01);
|
|
Wait;
|
|
Death:
|
|
SPRK A 1 Bright A_FadeOut(0.05);
|
|
Wait;
|
|
}
|
|
}
|
|
|
|
Class UTViewSpark : UTSpark
|
|
{
|
|
Default
|
|
{
|
|
+NOCLIP;
|
|
-MISSILE;
|
|
BounceType "None";
|
|
}
|
|
Vector3 ofs, vvel;
|
|
|
|
override void Tick()
|
|
{
|
|
Actor.Tick();
|
|
if ( !target || !target.player )
|
|
{
|
|
Destroy();
|
|
return;
|
|
}
|
|
Vector3 x, y, z;
|
|
[x, y, z] = Matrix4.GetAxes(target.pitch,target.angle,target.roll);
|
|
Vector3 origin = x*ofs.x+y*ofs.y+z*ofs.z+(0,0,target.player.viewz);
|
|
SetOrigin(target.Vec2OffsetZ(origin.x,origin.y,origin.z),true);
|
|
bInvisible = (players[consoleplayer].camera != target);
|
|
if ( level.frozen || globalfreeze ) return;
|
|
ofs += vvel;
|
|
vvel.z -= 0.1;
|
|
scale *= 0.8;
|
|
if ( (scale.x <= 0.01) || (waterlevel > 0) ) Destroy();
|
|
}
|
|
}
|
|
|
|
Class UTChip : Actor
|
|
{
|
|
int deadtimer;
|
|
double rollvel, anglevel, pitchvel;
|
|
|
|
Default
|
|
{
|
|
Radius 2;
|
|
Height 2;
|
|
+NOBLOCKMAP;
|
|
+MISSILE;
|
|
+MOVEWITHSECTOR;
|
|
+THRUACTORS;
|
|
+NOTELEPORT;
|
|
+DONTSPLASH;
|
|
BounceType "Doom";
|
|
BounceFactor 0.3;
|
|
Gravity 0.7;
|
|
Scale 0.2;
|
|
}
|
|
override void PostBeginPlay()
|
|
{
|
|
Super.PostBeginPlay();
|
|
deadtimer = 0;
|
|
anglevel = FRandom[Junk](10,30)*RandomPick[Junk](-1,1);
|
|
pitchvel = FRandom[Junk](10,30)*RandomPick[Junk](-1,1);
|
|
rollvel = FRandom[Junk](10,30)*RandomPick[Junk](-1,1);
|
|
frame = Random[Junk](0,3);
|
|
scale *= Frandom[Junk](0.8,1.2);
|
|
}
|
|
override void Tick()
|
|
{
|
|
Super.Tick();
|
|
if ( level.frozen || globalfreeze ) return;
|
|
if ( InStateSequence(CurState,ResolveState("Death")) )
|
|
{
|
|
deadtimer++;
|
|
if ( deadtimer > 300 ) A_FadeOut(0.05);
|
|
return;
|
|
}
|
|
}
|
|
States
|
|
{
|
|
Spawn:
|
|
CHIP # 1
|
|
{
|
|
A_SetAngle(angle+anglevel,SPF_INTERPOLATE);
|
|
A_SetPitch(pitch+pitchvel,SPF_INTERPOLATE);
|
|
A_SetRoll(roll+rollvel,SPF_INTERPOLATE);
|
|
}
|
|
Loop;
|
|
Bounce:
|
|
CHIP # 0
|
|
{
|
|
anglevel = FRandom[Junk](10,30)*RandomPick[Junk](-1,1);
|
|
pitchvel = FRandom[Junk](10,30)*RandomPick[Junk](-1,1);
|
|
rollvel = FRandom[Junk](10,30)*RandomPick[Junk](-1,1);
|
|
}
|
|
Goto Spawn;
|
|
Death:
|
|
CHIP # -1;
|
|
Stop;
|
|
Dummy:
|
|
CHIP ABCD -1;
|
|
Stop;
|
|
}
|
|
}
|
|
|
|
Class UTBubble : Actor
|
|
{
|
|
Default
|
|
{
|
|
RenderStyle "Add";
|
|
Radius 2;
|
|
Height 2;
|
|
+NOBLOCKMAP;
|
|
+NOGRAVITY;
|
|
+DONTSPLASH;
|
|
+FORCEXYBILLBOARD;
|
|
+NOTELEPORT;
|
|
Scale 0.05;
|
|
}
|
|
override void PostBeginPlay()
|
|
{
|
|
Super.PostBeginPlay();
|
|
double ang, pt;
|
|
scale *= FRandom[Puff](0.5,1.5);
|
|
ang = FRandom[Puff](0,360);
|
|
pt = FRandom[Puff](-90,90);
|
|
vel += (cos(pt)*cos(ang),cos(pt)*sin(ang),-sin(pt))*FRandom[Puff](0.2,0.8);
|
|
if ( waterlevel <= 0 ) Destroy();
|
|
SetState(ResolveState("Spawn")+Random[Puff](0,2));
|
|
}
|
|
override void Tick()
|
|
{
|
|
Super.Tick();
|
|
if ( level.frozen || globalfreeze ) return;
|
|
vel *= 0.96;
|
|
vel.z += 0.05;
|
|
if ( (waterlevel <= 0) || !Random[Puff](0,100) ) Destroy();
|
|
}
|
|
States
|
|
{
|
|
Spawn:
|
|
BUBL ABC -1;
|
|
Stop;
|
|
}
|
|
}
|
|
|
|
Class UTSmoke : Actor
|
|
{
|
|
Default
|
|
{
|
|
RenderStyle "Shaded";
|
|
StencilColor "FFFFFF";
|
|
Radius 2;
|
|
Height 2;
|
|
+NOBLOCKMAP;
|
|
+NOGRAVITY;
|
|
+DONTSPLASH;
|
|
+FORCEXYBILLBOARD;
|
|
+THRUACTORS;
|
|
+NOTELEPORT;
|
|
+CANBOUNCEWATER;
|
|
-BOUNCEAUTOOFF;
|
|
BounceType "Hexen";
|
|
BounceFactor 1.0;
|
|
WallBounceFactor 1.0;
|
|
Scale 0.5;
|
|
}
|
|
|
|
override void PostBeginPlay()
|
|
{
|
|
Super.PostBeginPlay();
|
|
double ang, pt;
|
|
scale *= FRandom[Puff](0.5,1.5);
|
|
alpha *= FRandom[Puff](0.5,1.5);
|
|
ang = FRandom[Puff](0,360);
|
|
pt = FRandom[Puff](-90,90);
|
|
vel += (cos(pt)*cos(ang),cos(pt)*sin(ang),-sin(pt))*FRandom[Puff](0.2,0.8);
|
|
}
|
|
override void Tick()
|
|
{
|
|
Super.Tick();
|
|
if ( level.frozen || globalfreeze ) return;
|
|
vel *= 0.96;
|
|
vel.z += 0.01;
|
|
A_FadeOut(1/32.);
|
|
if ( waterlevel > 0 )
|
|
{
|
|
let b = Spawn("UTBubble",pos);
|
|
b.vel = vel;
|
|
Destroy();
|
|
}
|
|
}
|
|
|
|
States
|
|
{
|
|
Spawn:
|
|
TNT1 A 0 NoDelay A_Jump(255,"US1","US2","US3","US4","US5","US6","US7","US8","US9","US10");
|
|
Stop;
|
|
US1:
|
|
US1_ ABCDEFGHIJKLMNOP 2;
|
|
Stop;
|
|
US2:
|
|
US2_ ABCDEFGHIJKLMNOP 2;
|
|
Stop;
|
|
US3:
|
|
US3_ ABCDEFGHIJKLMNOP 2;
|
|
Stop;
|
|
US4:
|
|
US4_ ABCDEFGHIJKLMNO 2;
|
|
Stop;
|
|
US5:
|
|
US5_ ABCDEFGHIJKLMNO 2;
|
|
Stop;
|
|
US6:
|
|
US6_ ABCDEFGHIJKLMNOP 2;
|
|
Stop;
|
|
US7:
|
|
US7_ ABCDEFGHIJKLMNOP 2;
|
|
Stop;
|
|
US8:
|
|
US8_ ABCDEFGHIJKLMNOP 2;
|
|
Stop;
|
|
US9:
|
|
US9_ ABCDEFGHIJKLMNOP 2;
|
|
Stop;
|
|
US10:
|
|
US10 ABCDEFGHIJKLMNOP 2;
|
|
Stop;
|
|
}
|
|
}
|
|
|
|
Class UTSmallSmoke : UTSmoke
|
|
{
|
|
override void PostBeginPlay()
|
|
{
|
|
Actor.PostBeginPlay();
|
|
double ang, pt;
|
|
scale *= FRandom[Puff](0.1,0.3);
|
|
alpha *= FRandom[Puff](0.5,1.5);
|
|
ang = FRandom[Puff](0,360);
|
|
pt = FRandom[Puff](-90,90);
|
|
vel += (cos(pt)*cos(ang),cos(pt)*sin(ang),-sin(pt))*FRandom[Puff](0.04,0.16);
|
|
}
|
|
}
|
|
|
|
Class UTViewSmoke : UTSmoke
|
|
{
|
|
Vector3 ofs, vvel;
|
|
|
|
override void PostBeginPlay()
|
|
{
|
|
Actor.PostBeginPlay();
|
|
double ang, pt;
|
|
scale *= FRandom[Puff](0.1,0.3);
|
|
alpha *= FRandom[Puff](0.5,1.5);
|
|
ang = FRandom[Puff](0,360);
|
|
pt = FRandom[Puff](-90,90);
|
|
vvel += (cos(pt)*cos(ang),cos(pt)*sin(ang),-sin(pt))*FRandom[Puff](0.04,0.16);
|
|
}
|
|
|
|
override void Tick()
|
|
{
|
|
Actor.Tick();
|
|
if ( !target || !target.player )
|
|
{
|
|
Destroy();
|
|
return;
|
|
}
|
|
Vector3 x, y, z;
|
|
[x, y, z] = Matrix4.GetAxes(target.pitch,target.angle,target.roll);
|
|
Vector3 origin = x*ofs.x+y*ofs.y+z*ofs.z+(0,0,target.player.viewz);
|
|
SetOrigin(target.Vec2OffsetZ(origin.x,origin.y,origin.z),true);
|
|
bInvisible = (players[consoleplayer].camera != target);
|
|
if ( level.frozen || globalfreeze ) return;
|
|
ofs += vvel;
|
|
vvel *= 0.96;
|
|
vvel.z += 0.01;
|
|
A_FadeOut(1/32.);
|
|
if ( waterlevel > 0 ) Destroy();
|
|
}
|
|
}
|
|
|
|
Class UTStaticViewSmoke : UTViewSmoke
|
|
{
|
|
override void PostBeginPlay()
|
|
{
|
|
Actor.PostBeginPlay();
|
|
scale *= FRandom[Puff](0.1,0.3);
|
|
alpha *= FRandom[Puff](0.5,1.5);
|
|
}
|
|
}
|
|
|
|
Class UTRedSkull : RedSkull replaces RedSkull
|
|
{
|
|
Default
|
|
{
|
|
Tag "Red Skull";
|
|
Species "RedSkull";
|
|
Inventory.PickupMessage "You got the Red Skull.";
|
|
}
|
|
States
|
|
{
|
|
Spawn:
|
|
USKL A -1;
|
|
Stop;
|
|
}
|
|
}
|
|
|
|
Class UTGoldSkull : YellowSkull replaces YellowSkull
|
|
{
|
|
Default
|
|
{
|
|
Tag "Gold Skull";
|
|
Species "YellowSkull";
|
|
Inventory.PickupMessage "You got the Gold Skull.";
|
|
}
|
|
States
|
|
{
|
|
Spawn:
|
|
USKL B -1;
|
|
Stop;
|
|
}
|
|
}
|
|
|
|
Class UTBlueSkull : BlueSkull replaces BlueSkull
|
|
{
|
|
Default
|
|
{
|
|
Tag "Blue Skull";
|
|
Species "BlueSkull";
|
|
Inventory.PickupMessage "You got the Blue Skull.";
|
|
}
|
|
States
|
|
{
|
|
Spawn:
|
|
USKL C -1;
|
|
Stop;
|
|
}
|
|
}
|
|
|
|
Class UTRedKey : RedCard replaces RedCard
|
|
{
|
|
Default
|
|
{
|
|
Tag "Red Key";
|
|
Species "RedCard";
|
|
Inventory.PickupMessage "You got the Red Key.";
|
|
}
|
|
States
|
|
{
|
|
Spawn:
|
|
UKEY A -1;
|
|
Stop;
|
|
}
|
|
}
|
|
|
|
Class UTGoldKey : YellowCard replaces YellowCard
|
|
{
|
|
Default
|
|
{
|
|
Tag "Gold Key";
|
|
Species "YellowCard";
|
|
Inventory.PickupMessage "You got the Gold Key.";
|
|
}
|
|
States
|
|
{
|
|
Spawn:
|
|
UKEY B -1;
|
|
Stop;
|
|
}
|
|
}
|
|
|
|
Class UTBlueKey : BlueCard replaces BlueCard
|
|
{
|
|
Default
|
|
{
|
|
Tag "Blue Key";
|
|
Species "BlueCard";
|
|
Inventory.PickupMessage "You got the Blue Key.";
|
|
}
|
|
States
|
|
{
|
|
Spawn:
|
|
UKEY C -1;
|
|
Stop;
|
|
}
|
|
}
|
|
|
|
Class GenericFlash : HUDMessageBase
|
|
{
|
|
Color col;
|
|
int duration;
|
|
double alpha;
|
|
Actor cam;
|
|
GenericFlash Setup( Actor camera, Color c, int d )
|
|
{
|
|
alpha = 1.0;
|
|
col = c;
|
|
duration = d;
|
|
cam = camera;
|
|
return self;
|
|
}
|
|
override bool Tick()
|
|
{
|
|
alpha -= 1./duration;
|
|
return (alpha<=0);
|
|
}
|
|
override void Draw( int bottom, int visibility )
|
|
{
|
|
if ( automapactive || (visibility != BaseStatusBar.HUDMSGLayer_UnderHUD) ) return;
|
|
if ( cam && (players[consoleplayer].camera != cam) ) return;
|
|
Screen.Dim(col,(col.a/255.)*alpha,0,0,Screen.GetWidth(),Screen.GetHeight());
|
|
}
|
|
}
|
|
|
|
Class QueuedFlash
|
|
{
|
|
Color c;
|
|
int duration;
|
|
int tic;
|
|
Actor cam;
|
|
}
|
|
|
|
Class UTMainHandler : StaticEventHandler
|
|
{
|
|
ui TextureID tex;
|
|
Array<QueuedFlash> flashes;
|
|
transient CVar nobosstelefrag;
|
|
|
|
private Actor AddLight( Vector3 pos, Color col, int radius )
|
|
{
|
|
Actor l = Actor.Spawn("PointLightAttenuated",pos);
|
|
if ( !l ) return null;
|
|
l.args[0] = col.r;
|
|
l.args[1] = col.g;
|
|
l.args[2] = col.b;
|
|
l.args[3] = radius;
|
|
return l;
|
|
}
|
|
|
|
private Actor AddAmbient( Vector3 pos, String snd, double volume = 1., double attenuation = ATTN_NORM )
|
|
{
|
|
Actor a = Actor.Spawn("MapSpot",pos);
|
|
if ( !a ) return null;
|
|
a.A_PlaySound(snd,CHAN_BODY,volume,true,attenuation);
|
|
return a;
|
|
}
|
|
|
|
override void WorldLoaded( WorldEvent e )
|
|
{
|
|
if ( gamestate != GS_LEVEL || e.IsSaveGame ) return;
|
|
// prettify Kinsie's test map for a more Unreal feel
|
|
if ( level.GetChecksum() ~== "FBC3B6622A8B74AE06DE01E70007AC33" )
|
|
{
|
|
TextureID deftex = TexMan.CheckForTexture("-noflat-",TexMan.Type_Any);
|
|
TextureID skytx = TexMan.CheckForTexture("BlueSky",TexMan.Type_Any);
|
|
TextureID baseflor = TexMan.CheckForTexture("rClfFlr0",TexMan.Type_Any);
|
|
TextureID baseceil = TexMan.CheckForTexture("rClfBas0",TexMan.Type_Any);
|
|
TextureID basewall = TexMan.CheckForTexture("uAlnWl2b",TexMan.Type_Any);
|
|
TextureID xbasewall = TexMan.CheckForTexture("xAlnWl2b",TexMan.Type_Any);
|
|
TextureID glasstex = TexMan.CheckForTexture("Glassg",TexMan.Type_Any);
|
|
level.ChangeSky(skytx,skytx);
|
|
for ( int i=0; i<level.sectors.size(); i++ )
|
|
{
|
|
level.sectors[i].lightlevel = 0;
|
|
level.sectors[i].SetPlaneLight(0,0);
|
|
level.sectors[i].SetPlaneLight(1,0);
|
|
// open some ceilings
|
|
if ( level.sectors[i].ceilingplane.ZAtPoint(level.sectors[i].centerspot) == 1280 )
|
|
level.sectors[i].SetTexture(1,skyflatnum);
|
|
if ( level.sectors[i].GetTexture(0) == deftex )
|
|
{
|
|
level.sectors[i].SetTexture(0,(i==47)?baseceil:baseflor);
|
|
level.sectors[i].SetXScale(0,2.);
|
|
level.sectors[i].SetYScale(0,2.);
|
|
}
|
|
if ( level.sectors[i].GetTexture(1) == deftex )
|
|
{
|
|
level.sectors[i].SetTexture(1,(i==47)?baseflor:baseceil);
|
|
level.sectors[i].SetXScale(1,2.);
|
|
level.sectors[i].SetYScale(1,2.);
|
|
}
|
|
}
|
|
for ( int i=0; i<level.sides.size(); i++ )
|
|
{
|
|
level.sides[i].light = 0;
|
|
for ( int j=0; j<3; j++ )
|
|
{
|
|
if ( level.sides[i].GetTexture(j) != deftex ) continue;
|
|
if ( (i==529) || (i==530) || (i==533) || (i==534) )
|
|
{
|
|
level.sides[i].SetTexture(j,xbasewall);
|
|
level.sides[i].SetTextureYOffset(j,-2304);
|
|
}
|
|
else level.sides[i].SetTexture(j,basewall);
|
|
level.sides[i].SetTextureXScale(j,2.);
|
|
level.sides[i].SetTextureYScale(j,2.);
|
|
}
|
|
}
|
|
// fixup
|
|
for ( int i=215; i<246; i++ )
|
|
{
|
|
if ( (i==218) || (i==221) || (i==227)
|
|
|| (i==230) || (i==232) || (i==234)
|
|
|| (i==238) || (i==243) ) continue;
|
|
level.sectors[i].SetSpecialColor(0,"00 00 00");
|
|
}
|
|
level.sectors[53].SetFade("00 00 20");
|
|
level.sides[1844].SetTexture(1,glasstex);
|
|
level.lines[945].alpha = 0.5;
|
|
AddLight((0,-288,128),"E0 E0 FF",256);
|
|
AddLight((-2560,1024,1280),"E0 E0 FF",1024);
|
|
AddLight((0,1024,1280),"E0 E0 FF",1024);
|
|
AddLight((2560,1024,1280),"E0 E0 FF",1024);
|
|
AddLight((-384,-160,64),"FF FF FF",128);
|
|
AddLight((-384,-288,64),"FF FF FF",128);
|
|
AddLight((-384,-416,64),"FF FF FF",128);
|
|
AddLight((0,2816,96),"FF FF FF",512);
|
|
AddLight((2904,1344,128),"80 80 FF",256);
|
|
AddLight((3408,1344,128),"80 80 FF",256);
|
|
AddLight((1568,1760,64),"20 20 80",128);
|
|
AddLight((1824,1760,64),"80 20 20",128);
|
|
AddLight((2080,1760,64),"FF 80 20",128);
|
|
AddLight((2336,1760,64),"20 FF 20",128);
|
|
AddLight((2592,1760,64),"80 80 20",128);
|
|
AddLight((2848,1760,64),"A0 A0 30",128);
|
|
AddLight((2944,960,64),"20 FF 20",128);
|
|
AddLight((2944,736,64),"20 FF 20",128);
|
|
AddLight((3264,960,64),"FF 20 20",128);
|
|
AddLight((3264,736,64),"A0 A0 30",128);
|
|
AddLight((3264,512,64),"80 80 20",128);
|
|
AddLight((3584,960,64),"80 80 20",128);
|
|
AddLight((3584,736,64),"20 FF 20",128);
|
|
AddLight((3584,512,64),"FF 80 20",128);
|
|
AddLight((3584,288,64),"FF 80 FF",128);
|
|
AddAmbient((0,-288,192),"testamb/wind1",0.5,1.6);
|
|
AddAmbient((-2560,1024,768),"testamb/wind1",0.4,0.8);
|
|
AddAmbient((0,1024,768),"testamb/wind1",0.4,0.8);
|
|
AddAmbient((2560,1024,768),"testamb/wind1",0.4,0.8);
|
|
AddAmbient((768,1600,1280),"testamb/wind2",0.8,1.6);
|
|
AddAmbient((3174,1344,128),"testamb/water",0.4,1.6);
|
|
AddAmbient((1568,1760,64),"testamb/water",0.4,2.4);
|
|
AddAmbient((2080,1760,64),"testamb/lava",0.8,2.4);
|
|
AddAmbient((2336,1760,64),"testamb/slime",0.4,2.4);
|
|
AddAmbient((2944,960,64),"testamb/slime",0.4,2.4);
|
|
AddAmbient((2944,736,64),"testamb/slime",0.4,2.4);
|
|
AddAmbient((3584,736,64),"testamb/slime",0.4,2.4);
|
|
AddAmbient((3584,512,64),"testamb/lava",0.8,2.4);
|
|
}
|
|
}
|
|
|
|
override void WorldThingSpawned( WorldEvent e )
|
|
{
|
|
if ( !nobosstelefrag ) nobosstelefrag = CVar.GetCVar('flak_nobosstelefrag');
|
|
if ( nobosstelefrag.GetBool() && e.Thing.bBOSS ) e.Thing.bNOTELEFRAG = true;
|
|
}
|
|
|
|
ui void StartMenu()
|
|
{
|
|
CVar protomenu = CVar.GetCVar('flak_protomenu',players[consoleplayer]);
|
|
if ( !protomenu ) return; // this can happen
|
|
int proto = protomenu.GetInt();
|
|
if ( proto )
|
|
{
|
|
tex = TexMan.CheckForTexture("protobg",TexMan.Type_Any);
|
|
if ( gamestate != GS_TITLELEVEL ) return;
|
|
if ( proto > 1 ) S_ChangeMusic("menu2");
|
|
else S_ChangeMusic("xyzdMenu");
|
|
}
|
|
else
|
|
{
|
|
tex = TexMan.CheckForTexture("finalbg",TexMan.Type_Any);
|
|
if ( gamestate != GS_TITLELEVEL ) return;
|
|
S_ChangeMusic("utmenu23");
|
|
}
|
|
}
|
|
|
|
override void PlayerEntered( PlayerEvent e )
|
|
{
|
|
if ( CVar.GetCVar('flak_translocator').GetBool() )
|
|
players[e.playernumber].mo.GiveInventory("Translocator",1);
|
|
}
|
|
override void PlayerRespawned( PlayerEvent e )
|
|
{
|
|
if ( CVar.GetCVar('flak_translocator').GetBool() )
|
|
players[e.playernumber].mo.GiveInventory("Translocator",1);
|
|
}
|
|
|
|
override void NetworkProcess( ConsoleEvent e )
|
|
{
|
|
if ( e.Name ~== "refreshtrans" )
|
|
{
|
|
if ( CVar.GetCVar('flak_translocator').GetBool() )
|
|
{
|
|
for ( int i=0; i<MAXPLAYERS; i++ ) if ( playeringame[i] ) players[i].mo.GiveInventory("Translocator",1);
|
|
}
|
|
else
|
|
{
|
|
for ( int i=0; i<MAXPLAYERS; i++ ) if ( playeringame[i] ) players[i].mo.TakeInventory("Translocator",1);
|
|
}
|
|
}
|
|
}
|
|
|
|
override void ConsoleProcess( ConsoleEvent e )
|
|
{
|
|
if ( e.Name ~== "refreshmenu" ) StartMenu();
|
|
if ( e.Name ~== "refreshtrans" ) EventHandler.SendNetworkEvent("refreshtrans");
|
|
}
|
|
|
|
override void WorldTick()
|
|
{
|
|
for ( int i=0; i<flashes.size(); i++ )
|
|
{
|
|
if ( flashes[i].tic >= gametic ) continue;
|
|
flashes.Delete(i);
|
|
i--;
|
|
}
|
|
}
|
|
|
|
override void PostUiTick()
|
|
{
|
|
for ( int i=0; i<flashes.size(); i++ )
|
|
{
|
|
if ( flashes[i].tic < gametic ) continue;
|
|
GenericFlash gf = new("GenericFlash").Setup(flashes[i].cam,flashes[i].c,flashes[i].duration);
|
|
StatusBar.AttachMessage(gf,0,BaseStatusBar.HUDMSGLayer_UnderHUD);
|
|
}
|
|
if ( gametic <= 0 ) StartMenu();
|
|
}
|
|
|
|
override void RenderOverlay( RenderEvent e )
|
|
{
|
|
if ( !menuactive ) return;
|
|
if ( tex.IsNull() || !tex.IsValid() ) return;
|
|
if ( !CVar.GetCVar('flak_showmenu',players[consoleplayer]).GetBool() ) return;
|
|
Screen.Dim("Black",1.0,0,0,Screen.GetWidth(),Screen.GetHeight());
|
|
Screen.DrawTexture(tex,true,0,0,DTA_VirtualWidth,1024,DTA_VirtualHeight,768);
|
|
}
|
|
|
|
static void DoFlash( Actor camera, Color c, int duration )
|
|
{
|
|
QueuedFlash qf = new("QueuedFlash");
|
|
qf.duration = duration;
|
|
qf.c = c;
|
|
qf.tic = gametic;
|
|
qf.cam = camera;
|
|
let hnd = UTMainHandler(StaticEventHandler.Find("UTMainHandler"));
|
|
hnd.flashes.push(qf);
|
|
}
|
|
|
|
// Doom's explosions aren't fully 3D
|
|
static void DoBlast( Actor Source, double ExplosionRadius, double MomentumTransfer )
|
|
{
|
|
BlockThingsIterator bi = BlockThingsIterator.Create(Source,ExplosionRadius);
|
|
while ( bi.Next() )
|
|
{
|
|
Actor a = bi.Thing;
|
|
if ( !a || !a.bSHOOTABLE || !Source.CheckSight(a,0xf) || (a == Source) || (Source.Distance3D(a) > ExplosionRadius) )
|
|
continue;
|
|
Vector3 midpoint = a.Vec3Offset(0,0,a.height*0.5);
|
|
a.vel += Level.Vec3Diff(Source.pos,midpoint).unit()*(MomentumTransfer/(Thinker.TICRATE*a.mass));
|
|
}
|
|
}
|
|
|
|
// Same for this
|
|
static void DoKnockback( Actor Victim, Vector3 HitDirection, double MomentumTransfer )
|
|
{
|
|
if ( !Victim ) return;
|
|
Victim.vel += HitDirection*(MomentumTransfer/(Thinker.TICRATE*Victim.Mass));
|
|
}
|
|
}
|