Support new versions of Kinsie's test map. Switch to new GetAxes implementation across the board. Minor fixes here and there.
546 lines
12 KiB
Text
546 lines
12 KiB
Text
Class UDamage : PowerupGiver
|
|
{
|
|
Default
|
|
{
|
|
Tag "$T_UDAMAGE";
|
|
Inventory.PickupMessage "$I_UDAMAGE";
|
|
+COUNTITEM;
|
|
+INVENTORY.AUTOACTIVATE;
|
|
+INVENTORY.ALWAYSPICKUP;
|
|
+INVENTORY.BIGPOWERUP;
|
|
Inventory.MaxAmount 0;
|
|
Powerup.Type "DamageAmplifier";
|
|
Inventory.PickupSound "udamage/pickup";
|
|
Inventory.RespawnTics 4200;
|
|
}
|
|
States
|
|
{
|
|
Spawn:
|
|
UDAM A -1;
|
|
Stop;
|
|
}
|
|
}
|
|
|
|
Class DamageAmpLight : DynamicLight
|
|
{
|
|
Default
|
|
{
|
|
DynamicLight.Type "Point";
|
|
Args 238,0,255,80;
|
|
}
|
|
override void Tick()
|
|
{
|
|
Super.Tick();
|
|
if ( !target || !master )
|
|
{
|
|
Destroy();
|
|
return;
|
|
}
|
|
if ( target.player )
|
|
SetOrigin(target.Vec2OffsetZ(0,0,target.player.viewz),true);
|
|
else SetOrigin(target.Vec3Offset(0,0,target.height/2),true);
|
|
args[LIGHT_INTENSITY] = Random[ASMD](10,12)*8;
|
|
bDORMANT = Powerup(master).isBlinking();
|
|
}
|
|
}
|
|
|
|
Class DamageAmplifier : Powerup
|
|
{
|
|
Actor l;
|
|
|
|
Default
|
|
{
|
|
Powerup.Duration -60;
|
|
Powerup.Color "EE00FF", 0.05;
|
|
}
|
|
|
|
override void BeginPlay()
|
|
{
|
|
Super.BeginPlay();
|
|
if ( deathmatch ) EffectTics /= 2;
|
|
}
|
|
|
|
override void InitEffect()
|
|
{
|
|
Super.InitEffect();
|
|
l = Spawn("DamageAmpLight",Owner.pos);
|
|
l.target = Owner;
|
|
l.master = self;
|
|
}
|
|
|
|
override void DoEffect()
|
|
{
|
|
Super.DoEffect();
|
|
if ( (EffectTics == 175) || (EffectTics == 140) || (EffectTics == 105) || (EffectTics == 70) || (EffectTics == 35) )
|
|
Owner.A_PlaySound("udamage/drain",CHAN_7,1.0,false,0.25);
|
|
}
|
|
|
|
override void EndEffect()
|
|
{
|
|
Super.EndEffect();
|
|
if ( EffectTics <= 0 ) PrintPickupMessage(true,StringTable.Localize("$D_UDAMAGE"));
|
|
}
|
|
|
|
override bool isBlinking()
|
|
{
|
|
return ((EffectTics <= 175) && (EffectTics%35 >= 30));
|
|
}
|
|
|
|
void FireEffect()
|
|
{
|
|
if ( EffectTics < 350 ) Owner.A_PlaySound("udamage/fire2",CHAN_7,1.0,false,0.25);
|
|
else Owner.A_PlaySound("udamage/fire1",CHAN_7,1.0,false,0.25);
|
|
UTMainHandler.DoFlash(Owner,Color(96,238,0,255),10);
|
|
}
|
|
|
|
override void ModifyDamage( int damage, Name damageType, out int newdamage, bool passive )
|
|
{
|
|
if ( passive || (damage <= 0) ) return;
|
|
newdamage = max(1,ApplyDamageFactors(GetClass(),damageType,damage,damage*3));
|
|
if ( !(Owner.player.ReadyWeapon is 'UTWeapon') ) FireEffect();
|
|
}
|
|
}
|
|
|
|
// Backpack that only gives ammo for valid weapons
|
|
Class UTBackpack : BackpackItem
|
|
{
|
|
override Inventory CreateCopy( Actor other )
|
|
{
|
|
// Find every unique type of ammoitem. Give it to the player if
|
|
// he doesn't have it already, and double its maximum capacity.
|
|
for ( int i=0; i<AllActorClasses.Size(); i++ )
|
|
{
|
|
let type = (class<Ammo>)(AllActorClasses[i]);
|
|
if ( !type || (type.GetParentClass() != 'Ammo') ) continue;
|
|
// check that it's for a valid weapon
|
|
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 ( !other.player || !other.player.weapons.LocateWeapon(type2) || weap.bCheatNotWeapon ) continue;
|
|
if ( (weap.AmmoType1 == type) || (weap.AmmoType2 == type) )
|
|
{
|
|
isvalid = true;
|
|
break;
|
|
}
|
|
}
|
|
if ( !isvalid ) continue;
|
|
let ammoitem = Ammo(other.FindInventory(type));
|
|
int amount = GetDefaultByType(type).BackpackAmount;
|
|
// extra ammo in baby mode and nightmare mode
|
|
if ( !bIgnoreSkill ) amount = int(amount*G_SkillPropertyFloat(SKILLP_AmmoFactor));
|
|
if ( amount < 0 ) amount = 0;
|
|
if ( !ammoitem )
|
|
{
|
|
// The player did not have the ammoitem. Add it.
|
|
ammoitem = Ammo(Spawn(type));
|
|
ammoitem.Amount = bDepleted?0:amount;
|
|
if ( ammoitem.BackpackMaxAmount > ammoitem.MaxAmount )
|
|
ammoitem.MaxAmount = ammoitem.BackpackMaxAmount;
|
|
if ( ammoitem.Amount > ammoitem.MaxAmount )
|
|
ammoitem.Amount = ammoitem.MaxAmount;
|
|
ammoitem.AttachToOwner(other);
|
|
}
|
|
else
|
|
{
|
|
// The player had the ammoitem. Give some more.
|
|
if ( ammoitem.MaxAmount < ammoitem.BackpackMaxAmount )
|
|
ammoitem.MaxAmount = ammoitem.BackpackMaxAmount;
|
|
if ( !bDepleted && (ammoitem.Amount < ammoitem.MaxAmount) )
|
|
{
|
|
ammoitem.Amount += amount;
|
|
if ( ammoitem.Amount > ammoitem.MaxAmount )
|
|
ammoitem.Amount = ammoitem.MaxAmount;
|
|
}
|
|
}
|
|
}
|
|
return Inventory.CreateCopy(other);
|
|
}
|
|
override bool HandlePickup (Inventory item)
|
|
{
|
|
// Since you already have a backpack, that means you already have every
|
|
// kind of ammo in your inventory, so we don't need to look at the
|
|
// entire PClass list to discover what kinds of ammo exist, and we don't
|
|
// have to alter the MaxAmount either.
|
|
if ( item is 'BackpackItem' )
|
|
{
|
|
for ( let probe = Owner.Inv; probe; probe = probe.Inv )
|
|
{
|
|
if ( probe.GetParentClass() != 'Ammo' ) continue;
|
|
if ( probe.Amount >= probe.MaxAmount && !sv_unlimited_pickup ) continue;
|
|
int amount = Ammo(probe).Default.BackpackAmount;
|
|
// extra ammo in baby mode and nightmare mode
|
|
if ( !bIgnoreSkill )
|
|
amount = int(amount*G_SkillPropertyFloat(SKILLP_AmmoFactor));
|
|
probe.Amount += amount;
|
|
if ( (probe.Amount > probe.MaxAmount) && !sv_unlimited_pickup )
|
|
probe.Amount = probe.MaxAmount;
|
|
}
|
|
// The pickup always succeeds, even if you didn't get anything
|
|
item.bPickupGood = true;
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
Default
|
|
{
|
|
Tag "$T_BACKPACK";
|
|
Inventory.PickupMessage "$I_BACKPACK";
|
|
Inventory.RespawnTics 2100;
|
|
}
|
|
States
|
|
{
|
|
Spawn:
|
|
BPAK A -1;
|
|
Stop;
|
|
}
|
|
}
|
|
|
|
Class PowerUTInvisibility : PowerInvisibility
|
|
{
|
|
Default
|
|
{
|
|
Powerup.Duration -100;
|
|
Powerup.Strength 90;
|
|
Powerup.Mode "Additive";
|
|
Powerup.Color "FFFFFF", 0.1;
|
|
}
|
|
override void BeginPlay()
|
|
{
|
|
Super.BeginPlay();
|
|
if ( deathmatch ) EffectTics /= 2;
|
|
}
|
|
override void EndEffect()
|
|
{
|
|
Super.EndEffect();
|
|
if ( EffectTics <= 0 ) PrintPickupMessage(true,StringTable.Localize("$D_INVISIBILITY"));
|
|
}
|
|
}
|
|
|
|
Class UTInvisibility : PowerupGiver
|
|
{
|
|
Default
|
|
{
|
|
Tag "$T_INVISIBILITY";
|
|
+COUNTITEM;
|
|
+INVENTORY.AUTOACTIVATE;
|
|
+INVENTORY.ALWAYSPICKUP;
|
|
+INVENTORY.BIGPOWERUP;
|
|
Inventory.MaxAmount 0;
|
|
Powerup.Type "PowerUTInvisibility";
|
|
Inventory.PickupMessage "$I_INVISIBILITY";
|
|
Inventory.PickupSound "invis/pickup";
|
|
Inventory.RespawnTics 4200;
|
|
}
|
|
override void PostBeginPlay()
|
|
{
|
|
Super.PostBeginPlay();
|
|
tracer = Spawn("UTInvisibilityX",pos);
|
|
tracer.angle = angle;
|
|
tracer.target = self;
|
|
}
|
|
States
|
|
{
|
|
Spawn:
|
|
INVS A -1;
|
|
Stop;
|
|
}
|
|
}
|
|
|
|
Class UTInvisibilityX : Actor
|
|
{
|
|
Default
|
|
{
|
|
RenderStyle "Add";
|
|
+NOGRAVITY;
|
|
+NOCLIP;
|
|
+DONTSPLASH;
|
|
Radius 0.1;
|
|
Height 0;
|
|
}
|
|
override void Tick()
|
|
{
|
|
Super.Tick();
|
|
if ( !target )
|
|
{
|
|
Destroy();
|
|
return;
|
|
}
|
|
Warp(target,flags:WARPF_COPYINTERPOLATION|WARPF_NOCHECKPOSITION);
|
|
bInvisible = target.bInvisible;
|
|
}
|
|
States
|
|
{
|
|
Spawn:
|
|
INVS A -1 Bright;
|
|
Stop;
|
|
}
|
|
}
|
|
|
|
Class UTMapRevealer : MapRevealer
|
|
{
|
|
Default
|
|
{
|
|
+COUNTITEM;
|
|
+INVENTORY.FANCYPICKUPSOUND;
|
|
+INVENTORY.ALWAYSPICKUP;
|
|
Inventory.MaxAmount 0;
|
|
Inventory.PickupSound "trans/pickup";
|
|
Inventory.PickupMessage "$I_MAPREVEALER";
|
|
}
|
|
States
|
|
{
|
|
Spawn:
|
|
TRNS A -1;
|
|
Stop;
|
|
}
|
|
}
|
|
|
|
Class UTJumpBoots : Inventory
|
|
{
|
|
Default
|
|
{
|
|
Tag "$T_JUMPBOOTS";
|
|
+INVENTORY.AUTOACTIVATE;
|
|
+INVENTORY.ALWAYSPICKUP;
|
|
Inventory.Amount 2100;
|
|
Inventory.MaxAmount 2100;
|
|
Inventory.InterHubAmount 2100;
|
|
Inventory.PickupMessage "$I_JUMPBOOTS";
|
|
Inventory.PickupSound "boot/pickup";
|
|
Inventory.RespawnTics 1050;
|
|
}
|
|
override bool Use( bool pickup )
|
|
{
|
|
if ( pickup )
|
|
{
|
|
Owner.GiveInventory("PowerJumpBoots_HighJump",1);
|
|
if ( flak_radboots )
|
|
Owner.GiveInventory("PowerJumpBoots_IronFeet",1);
|
|
}
|
|
return false;
|
|
}
|
|
override void Tick()
|
|
{
|
|
Super.Tick();
|
|
if ( !Owner || !Owner.player ) return;
|
|
if ( flak_radboots )
|
|
amount--;
|
|
if ( (amount > 0) && (owner.player.jumptics == -1) )
|
|
{
|
|
Amount = max(0,Amount-700);
|
|
Owner.A_PlaySound("boot/jump",CHAN_BODY);
|
|
}
|
|
else if ( (Amount <= 0) && owner.player.onground )
|
|
{
|
|
PrintPickupMessage(true,StringTable.Localize("$D_JUMPBOOTS"));
|
|
DepleteOrDestroy();
|
|
}
|
|
}
|
|
override void DetachFromOwner()
|
|
{
|
|
Super.DetachFromOwner();
|
|
Owner.TakeInventory("PowerJumpBoots_HighJump",1);
|
|
Owner.TakeInventory("PowerJumpBoots_IronFeet",1);
|
|
}
|
|
override void OwnerDied()
|
|
{
|
|
Super.OwnerDied();
|
|
DepleteOrDestroy();
|
|
}
|
|
States
|
|
{
|
|
Spawn:
|
|
JBUT A -1;
|
|
Stop;
|
|
}
|
|
}
|
|
|
|
Class PowerJumpBoots_HighJump : PowerHighJump
|
|
{
|
|
Default
|
|
{
|
|
Powerup.Strength 3;
|
|
Powerup.Duration int.max;
|
|
+INVENTORY.PERSISTENTPOWER;
|
|
}
|
|
}
|
|
Class PowerJumpBoots_IronFeet : PowerIronFeet
|
|
{
|
|
Default
|
|
{
|
|
Powerup.Duration int.max;
|
|
Powerup.Color "00 00 00", 0.0;
|
|
+INVENTORY.PERSISTENTPOWER;
|
|
}
|
|
override void AbsorbDamage( int damage, Name damageType, out int newdamage )
|
|
{
|
|
}
|
|
override void DoEffect()
|
|
{
|
|
Powerup.DoEffect();
|
|
if ( !flak_radboots )
|
|
DepleteOrDestroy();
|
|
}
|
|
}
|
|
|
|
Class Searchlight : Inventory
|
|
{
|
|
Actor lt[3];
|
|
int ticcnt;
|
|
Default
|
|
{
|
|
Tag "$T_SEARCHLIGHT";
|
|
+COUNTITEM;
|
|
+INVENTORY.UNTOSSABLE;
|
|
+INVENTORY.FANCYPICKUPSOUND;
|
|
+INVENTORY.AUTOACTIVATE;
|
|
+INVENTORY.ALWAYSPICKUP;
|
|
Inventory.Amount 200;
|
|
Inventory.MaxAmount 200;
|
|
Inventory.InterHubAmount 0;
|
|
Inventory.PickupMessage "$I_SEARCHLIGHT";
|
|
Inventory.PickupSound "lite/pickup";
|
|
Inventory.RespawnTics 1050;
|
|
}
|
|
|
|
override bool Use( bool pickup )
|
|
{
|
|
if ( !lt[0] ) lt[0] = Spawn("mkLight");
|
|
lt[0].target = owner;
|
|
lt[0].master = self;
|
|
if ( !lt[1] ) lt[1] = Spawn("mkLight2");
|
|
lt[1].target = owner;
|
|
lt[1].master = self;
|
|
if ( !lt[2] ) lt[2] = Spawn("mkLight3");
|
|
lt[2].target = owner;
|
|
lt[2].master = self;
|
|
return Super.Use(pickup);
|
|
}
|
|
override void DetachFromOwner()
|
|
{
|
|
Super.DetachFromOwner();
|
|
if ( lt[0] ) lt[0].Destroy();
|
|
if ( lt[1] ) lt[1].Destroy();
|
|
if ( lt[2] ) lt[2].Destroy();
|
|
}
|
|
override void DoEffect()
|
|
{
|
|
Super.DoEffect();
|
|
if ( !Owner ) return;
|
|
if ( ticcnt++ < TICRATE ) return;
|
|
ticcnt = 0;
|
|
if ( --Amount <= 0 )
|
|
{
|
|
PrintPickupMessage(true,StringTable.Localize("$D_SEARCHLIGHT"));
|
|
DepleteOrDestroy();
|
|
}
|
|
}
|
|
States
|
|
{
|
|
Spawn:
|
|
SLIT A -1;
|
|
Stop;
|
|
}
|
|
}
|
|
|
|
/* hello, Soundless Mound copypasted lights */
|
|
Class mkLight : DynamicLight
|
|
{
|
|
int basecolor[3];
|
|
|
|
Default
|
|
{
|
|
DynamicLight.Type "Point";
|
|
+DynamicLight.SPOT;
|
|
+DynamicLight.ATTENUATE;
|
|
+DynamicLight.DONTLIGHTSELF;
|
|
args 255,224,160,300;
|
|
DynamicLight.SpotInnerAngle 20;
|
|
DynamicLight.SpotOuterAngle 35;
|
|
}
|
|
override void PostBeginPlay()
|
|
{
|
|
Super.PostBeginPlay();
|
|
basecolor[0] = args[LIGHT_RED];
|
|
basecolor[1] = args[LIGHT_GREEN];
|
|
basecolor[2] = args[LIGHT_BLUE];
|
|
}
|
|
override void Tick()
|
|
{
|
|
Super.Tick();
|
|
if ( !target || !Inventory(master) )
|
|
{
|
|
Destroy();
|
|
return;
|
|
}
|
|
if ( target.player ) SetOrigin((target.pos.x,target.pos.y,target.player.viewz),true);
|
|
else SetOrigin(target.vec3Offset(0,0,target.height*0.75),true);
|
|
A_SetAngle(target.angle,SPF_INTERPOLATE);
|
|
A_SetPitch(target.pitch,SPF_INTERPOLATE);
|
|
args[LIGHT_RED] = int(basecolor[0]*clamp(Inventory(master).amount/40.,0.,1.));
|
|
args[LIGHT_GREEN] = int(basecolor[1]*clamp(Inventory(master).amount/40.,0.,1.));
|
|
args[LIGHT_BLUE] = int(basecolor[2]*clamp(Inventory(master).amount/40.,0.,1.));
|
|
bDORMANT = (target.health <= 0);
|
|
if ( Inventory(target) && target.bInvisible ) bDORMANT = true;
|
|
// alert monsters hit by the light
|
|
if ( GetClass() != "mkLight" ) return;
|
|
if ( !bDORMANT && target.player && (target.health > 0) )
|
|
{
|
|
BlockThingsIterator bt = BlockThingsIterator.Create(target,args[LIGHT_INTENSITY]);
|
|
while ( bt.Next() )
|
|
{
|
|
if ( !bt.Thing || (Distance3D(bt.Thing) > args[LIGHT_INTENSITY]) ) continue;
|
|
Vector3 aimdir = (cos(angle)*cos(pitch),sin(angle)*cos(pitch),-sin(pitch));
|
|
Vector3 reldir = Vec3To(bt.Thing).unit();
|
|
if ( (acos(aimdir dot reldir) < SpotOuterAngle+5) && bt.Thing.CheckSight(target) ) bt.Thing.LastHeard = target;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
Class mkLight2 : mkLight
|
|
{
|
|
Default
|
|
{
|
|
args 128,112,96,300;
|
|
DynamicLight.SpotInnerAngle 0;
|
|
DynamicLight.SpotOuterAngle 50;
|
|
}
|
|
}
|
|
|
|
Class mkLight3 : DynamicLight
|
|
{
|
|
int basecolor[3];
|
|
|
|
Default
|
|
{
|
|
DynamicLight.Type "Point";
|
|
+DynamicLight.ATTENUATE;
|
|
args 32,28,24,0;
|
|
}
|
|
override void PostBeginPlay()
|
|
{
|
|
Super.PostBeginPlay();
|
|
basecolor[0] = args[LIGHT_RED];
|
|
basecolor[1] = args[LIGHT_GREEN];
|
|
basecolor[2] = args[LIGHT_BLUE];
|
|
}
|
|
override void Tick()
|
|
{
|
|
Super.Tick();
|
|
if ( !target || Inventory(target) || !Inventory(master) )
|
|
{
|
|
Destroy();
|
|
return;
|
|
}
|
|
args[LIGHT_RED] = int(basecolor[0]*clamp(Inventory(master).amount/40.,0.,1.));
|
|
args[LIGHT_GREEN] = int(basecolor[1]*clamp(Inventory(master).amount/40.,0.,1.));
|
|
args[LIGHT_BLUE] = int(basecolor[2]*clamp(Inventory(master).amount/40.,0.,1.));
|
|
SetOrigin(target.vec3Offset(0,0,target.height*0.5),true);
|
|
}
|
|
}
|