Release Candidate 3:

- Fix inventory items not removing themselves when fully drained and no more
  copies are held.
- Fixed Minigun playing the unwind animation on player death.
- Fixed main hand Automag still firing when out of ammo dual wielding.
- Corrected name clash between two explosion sounds.
- Fixed suits still protecting from elemental damage when depleted.
- Add option to wear all suits simultaneously.
- Stunner now consumes Stinger ammo to recharge, this is more in line with the
  Unreal Bible.
- Max damage per explosion capped to 100 for Stinger. Prevents ludicrous
  map-clearing explosions with an amplified asmd combo.
- Shoot-through lines can now be activated by hitscan/beam weapons thanks to
  new DT "bullet trail" feature. No more softlocks in custom maps.
- Added option to make Peacemaker missiles not seek owner and allies.
- Peacemaker missiles start seeking targets much earlier, making it more viable
  indoors.
- Autocannon has had its damage increased again.
- Adjusted swingers for many weapons to feel a bit more natural. Still far from
  perfect.
- Reverted changes to Flamethrower projectile density, and simply made it have
  less dynamic lights.
- Adjustments to armors. Suit elemental resistances now take priority (as
  intended). [please redownload your DT devbuild for full effect]
- Added ring effect for 6-rocket tight wad. Completely forgot this was a thing.
- Fixed flashlight not clearing its dynlights when depleted and still having
  copies.
This commit is contained in:
Marisa the Magician 2019-10-10 08:32:36 +02:00
commit c6a81479ca
29 changed files with 218 additions and 74 deletions

View file

@ -42,9 +42,9 @@ this the weapon will need a short time to load up ammunition again.
### Extended behaviour
With each shot, targets will be pumped with highly volatile Tarydium, and can
be detonated with fire from other weapons, or sufficient kinetic force (e.g.
making them fall from a considerable height).
With each shot, targets will be pumped with highly volatile Tarydium, resulting
in a thundering blast of sheer energy when hit with fire from other weapons, or
sufficient kinetic force (e.g. making them fall from a considerable height).
## ASMD
@ -169,8 +169,8 @@ complete opposite effect, causing targets to instead be pulled towards you.
Since the charge rod rapidly extends on shoot, both fire modes additionally
deal considerable melee damage to anything that's too close.
Its energy supply regenerates much quicker than the Dispersion Pistol, thanks
to superior Skaarj engineering.
Its energy supply will regenerate quickly, as long as you have plenty of
Tarydium Shards in your inventory.
## Razorclaw

View file

@ -91,3 +91,8 @@ server bool sting_flametspread = false; // targets on fire spread the flames
server bool sting_impself = false; // disable impaler beam self-hit
user bool sting_zoomshader = true; // rifle scope shader
server bool sting_proto = true; // allow prototype content
server bool sting_allsuits = false; // allow the player to wear all three
// types of suits simultaneously
// (this is very unbalanced)
server bool sting_peacehome = false; // peacemaker doesn't home in on owner
// or friendlies

View file

@ -255,6 +255,8 @@ STING_RAZORAIM = "Razorjack altfire follows the crosshair";
STING_BIOSPLASH = "Biorifle altfire splashes like in UT";
STING_FLAMETSPREAD = "Flamethrower fire spreads between targets";
STING_IMPSELF = "Impaler beam cannot hurt user";
STING_ALLSUITS = "Can wear all suits simultaneously";
STING_PEACEHOME = "Peacemaker missiles ignore owner and allies";
STING_MCREDS = "Unreal Credits";
STING_CDR = "Doomreal";
STING_CLEAD = "Development Lead:";
@ -499,6 +501,8 @@ STING_RAZORAIM = "El fuego alt. del Razorjack sigue el punto de mira";
STING_BIOSPLASH = "El fuego alt. del Biorifle salpica como en UT";
STING_FLAMETSPREAD = "El fuego del Lanzallamas se propaga entre objetivos";
STING_IMPSELF = "El haz del Empalador no daña al usuario";
STING_ALLSUITS = "Permitir uso de todos los trajes al mismo tiempo";
STING_PEACEHOME = "Los misiles Peacemaker ignoran al usuario y aliados";
STING_MCREDS = "Créditos de Unreal";
STING_CDR = "Doomreal";
STING_CLEAD = "Desarrolladora Jefe:";

View file

@ -55,6 +55,8 @@ OptionMenu "UnrealOptionMenu"
Option "$STING_BIOSPLASH", "sting_biosplash", "YesNo"
Option "$STING_FLAMETSPREAD", "sting_flametspread", "YesNo", "sting_proto"
Option "$STING_IMPSELF", "sting_impself", "YesNo", "sting_proto"
Option "$STING_ALLSUITS", "sting_allsuits", "YesNo"
Option "$STING_PEACEHOME", "sting_peacehome", "YesNo"
}
AddOptionMenu "OptionsMenu"

View file

@ -323,7 +323,7 @@ flamegun/fire flamgfir
flamegun/end flamgend
flamegun/charge flamgabg
flamegun/alt flamgalt
flamegun/exp expl2
flamegun/exp cexpl2
$limit flamegun/exp 16
flamegun/exp2 expl04

View file

@ -513,7 +513,10 @@ Class ASMDBeam : Actor
if ( isFrozen() || !moving ) return;
// step trace
tracedir = (cos(angle)*cos(pitch),sin(angle)*cos(pitch),-sin(pitch));
t.ShootThroughList.Clear();
t.Trace(pos,cursector,tracedir,1000,0);
for ( int i=0; i<t.ShootThroughList.Size(); i++ )
t.ShootThroughList[i].Activate(target,0,SPAC_PCross);
totaldist += t.Results.Distance;
// spawn particles
for ( int i=10; i<t.Results.Distance; i+=80 )

View file

@ -174,7 +174,7 @@ Class Automag : UnrealWeapon
else A_Overlay(-3,"LeftMuzzleFlash");
A_OverlayFlags(-3,PSPF_RENDERSTYLE|PSPF_FORCESTYLE,true);
A_OverlayRenderstyle(-3,STYLE_Add);
UTMainHandler.DoSwing(self,(FRandom[Automag](0.5,0.2),FRandom[Automag](-0.3,0.2)),2,0,1,SWING_Spring,0,2);
UTMainHandler.DoSwing(self,(FRandom[Automag](0.5,0.2),FRandom[Automag](-0.3,0.2)),2,0.5,1,SWING_Spring,0,2);
}
else
{
@ -195,6 +195,7 @@ Class Automag : UnrealWeapon
Vector3 dir = (x2+y2*cos(a)*s+z2*sin(a)*s).unit();
FLineTraceData d;
LineTrace(atan2(dir.y,dir.x),10000,asin(-dir.z),TRF_ABSPOSITION,origin.z,origin.x,origin.y,d);
UTBulletTrail.DoTrail(self,origin,dir,10000,int((invoker.Amount+alt)**2));
if ( d.HitType == TRACE_HitActor )
{
int dmg = 17;
@ -375,9 +376,10 @@ Class Automag : UnrealWeapon
TNT1 A 1
{
A_CheckReload();
int flags = (invoker.clipcount<=0)?WRF_NOFIRE:0;
if ( (invoker.clipcount <= 0) && (invoker.Ammo1.Amount > 0) ) player.SetPSprite(PSP_WEAPON,ResolveState("Reload"));
else if ( ((invoker.clipcount < invoker.default.clipcount) || (invoker.slaveclipcount < invoker.default.slaveclipcount)) && (invoker.Ammo1.Amount > 0) ) A_WeaponReady(WRF_ALLOWRELOAD|WRF_ALLOWZOOM);
else A_WeaponReady(WRF_ALLOWZOOM);
else if ( ((invoker.clipcount < invoker.default.clipcount) || (invoker.slaveclipcount < invoker.default.slaveclipcount)) && (invoker.Ammo1.Amount > 0) ) A_WeaponReady(flags|WRF_ALLOWRELOAD|WRF_ALLOWZOOM);
else A_WeaponReady(flags|WRF_ALLOWZOOM);
if ( !invoker.slaveactive && (CountInv("Automag") > 1) )
{
invoker.slavespin = invoker.slavereload = invoker.slaverefire = 0;

View file

@ -238,6 +238,7 @@ Class Betamag : UnrealWeapon
Vector3 dir = (x2+y2*cos(a)*s+z2*sin(a)*s).unit();
FLineTraceData d;
LineTrace(atan2(dir.y,dir.x),10000,asin(-dir.z),TRF_ABSPOSITION,origin.z,origin.x,origin.y,d);
UTBulletTrail.DoTrail(self,origin,dir,10000,int((invoker.Amount+alt)**2));
if ( d.HitType == TRACE_HitActor )
{
int dmg = 14;
@ -484,14 +485,14 @@ Class Betamag : UnrealWeapon
{
A_Overlay(-9999,null);
invoker.slavewhip = true;
UTMainHandler.DoSwing(self,(FRandom[Betamag](-0.5,-0.4),FRandom[Betamag](0.2,0.3)),4,0,8,SWING_Spring,5);
UTMainHandler.DoSwing(self,(FRandom[Betamag](-0.5,-0.4),FRandom[Betamag](0.2,0.3)),4,0.3,8,SWING_Spring,5);
}
AUTW ABCDE 2;
AUTW F 0
{
if ( self is 'UTPlayer' ) UTPlayer(self).PlayAttacking3();
A_PlaySound("betamag/whip",CHAN_ITEM);
UTMainHandler.DoSwing(self,(FRandom[Betamag](-0.3,-0.2),FRandom[Betamag](-0.8,-0.5)),2,0,8,SWING_Spring,2,0.5);
UTMainHandler.DoSwing(self,(FRandom[Betamag](-0.3,-0.2),FRandom[Betamag](-0.8,-0.5)),7,-1,8,SWING_Spring,2,0.5);
}
AUTW FGHIJ 2;
AUTW K 0
@ -515,7 +516,7 @@ Class Betamag : UnrealWeapon
if ( !((invoker.Ammo1.Amount<=0) && (player.cmd.buttons&(BT_ATTACK|BT_ALTATTACK))) && !(player.cmd.buttons&BT_RELOAD) ) return ResolveState("LeftIdle");
invoker.slavewhip = false;
A_Overlay(-9998,null);
UTMainHandler.DoSwing(self,(FRandom[Betamag](0.4,0.5),FRandom[Betamag](0.2,0.3)),4,0,8,SWING_Spring,5);
UTMainHandler.DoSwing(self,(FRandom[Betamag](0.4,0.5),FRandom[Betamag](0.2,0.3)),4,0.3,8,SWING_Spring,5);
return ResolveState(null);
}
2UTW ABCDE 2;
@ -523,7 +524,7 @@ Class Betamag : UnrealWeapon
{
if ( self is 'UTPlayer' ) UTPlayer(self).PlayAttacking3();
A_PlaySound("betamag/whip",CHAN_7);
UTMainHandler.DoSwing(self,(FRandom[Betamag](0.2,0.3),FRandom[Betamag](-0.8,-0.5)),2,0,8,SWING_Spring,2,0.5);
UTMainHandler.DoSwing(self,(FRandom[Betamag](0.2,0.3),FRandom[Betamag](-0.8,-0.5)),7,-1,8,SWING_Spring,2,0.5);
}
2UTW FGHIJ 2;
2UTW K 0

View file

@ -186,6 +186,7 @@ Class HitListEntry
Class BigTracer : LineTracer
{
Actor ignoreme;
Array<Line> ShootThroughList;
Array<HitListEntry> hitlist;
double penetration; // please don't laugh
@ -213,6 +214,7 @@ Class BigTracer : LineTracer
{
if ( !Results.HitLine.sidedef[1] || (Results.HitLine.Flags&(Line.ML_BlockHitscan|Line.ML_BlockEverything)) )
return TRACE_Stop;
ShootThroughList.Push(Results.HitLine);
return TRACE_Skip;
}
return TRACE_Stop;
@ -308,7 +310,7 @@ Class BigGun : UnrealWeapon
UTMainHandler.DoFlash(self,Color(32,255,128,0),1);
A_QuakeEx(2,2,2,3,0,1,"",QF_RELATIVE|QF_SCALEDOWN,rollintensity:0.12);
for ( int i=0; i<6; i++ )
UTMainHandler.DoSwing(self,(FRandom[BigGun](-0.04,-0.2),FRandom[BigGun](-0.2,0.2)),FRandom[BigGun](6,9),FRandom[BigGun](-0.2,0.8),Random[BigGun](2,4),SWING_Spring,Random[BigGun](3,6),FRandom[BigGun](1.5,2.3));
UTMainHandler.DoSwing(self,(FRandom[BigGun](-0.04,-0.2),FRandom[BigGun](-0.2,0.2)),FRandom[BigGun](6,9),FRandom[BigGun](-2,-3),Random[BigGun](2,4),SWING_Spring,Random[BigGun](3,4),FRandom[BigGun](1.5,2.3));
Vector3 x, y, z, x2, y2, z2;
[x, y, z] = dt_CoordUtil.GetAxes(pitch,angle,roll);
vel -= x*(player.onground?9.5:2.5);
@ -321,7 +323,16 @@ Class BigGun : UnrealWeapon
invoker.t.ignoreme = self;
invoker.t.hitlist.Clear();
invoker.t.penetration = 200.;
invoker.t.ShootThroughList.Clear();
invoker.t.Trace(origin,level.PointInSector(origin.xy),dir,10000.,0);
for ( int i=0; i<invoker.t.ShootThroughList.Size(); i++ )
invoker.t.ShootThroughList[i].Activate(self,0,SPAC_PCross);
for ( int i=5; i<invoker.t.Results.Distance; i+=10 )
{
if ( !Random[Boolet](0,bAlt?3:2) ) continue;
let b = Actor.Spawn("UTBubble",level.Vec3Offset(origin,dir*i));
b.Scale *= FRandom[Boolet](0.4,0.6);
}
for ( int i=0; i<invoker.t.hitlist.Size(); i++ )
{
let l = invoker.t.hitlist[i];
@ -462,7 +473,7 @@ Class BigGun : UnrealWeapon
BIGT BCDEFGHIJKLMNOP 2;
BIGT Q 2
{
UTMainHandler.DoSwing(self,(FRandom[BigGun](-0.3,-0.2),FRandom[BigGun](0.4,0.5)),3,0,6,SWING_Spring,2,1.5);
UTMainHandler.DoSwing(self,(FRandom[BigGun](-0.3,-0.2),FRandom[BigGun](0.4,0.5)),3,0.5,6,SWING_Spring,2,1.5);
}
BIGT RSTUVWXY 2;
Goto Idle;
@ -514,12 +525,12 @@ Class BigGun : UnrealWeapon
{
A_ClearRefire();
A_Overlay(-9999,"Null");
UTMainHandler.DoSwing(self,(FRandom[BigGun](0.7,0.3),FRandom[BigGun](0.4,0.3)),3,0,10,SWING_Spring,70,0.8);
UTMainHandler.DoSwing(self,(FRandom[BigGun](0.7,0.3),FRandom[BigGun](0.4,0.3)),3,0.2,10,SWING_Spring,70,0.8);
}
BIGR ABCDEFGHIJKL 2;
BIGR M 2
{
UTMainHandler.DoSwing(self,(FRandom[BigGun](0.3,0.4),FRandom[BigGun](0.6,0.8)),6,0,3,SWING_Spring,2,3);
UTMainHandler.DoSwing(self,(FRandom[BigGun](0.3,0.4),FRandom[BigGun](0.6,0.8)),6,-1,3,SWING_Spring,2,3);
invoker.clipout = true;
A_QuakeEx(2,2,2,5,0,1,"",QF_RELATIVE|QF_SCALEDOWN,rollintensity:0.18);
A_PlaySound("big/punch",CHAN_WEAPON,Dampener.Active(self)?.3:1.);
@ -529,7 +540,7 @@ Class BigGun : UnrealWeapon
BIR2 ABCDEF 2;
BIR2 G 2
{
UTMainHandler.DoSwing(self,(FRandom[BigGun](0.2,0.3),FRandom[BigGun](0.3,0.5)),6,0,3,SWING_Spring,2,3);
UTMainHandler.DoSwing(self,(FRandom[BigGun](0.2,0.3),FRandom[BigGun](0.3,0.5)),6,-1,3,SWING_Spring,2,3);
invoker.clipout = false;
let aadd = min(invoker.ammo1.amount,invoker.default.clipcount-invoker.clipcount);
invoker.clipcount += aadd;
@ -542,15 +553,19 @@ Class BigGun : UnrealWeapon
BIR2 M 2
{
invoker.PlayUpSound(self);
UTMainHandler.DoSwing(self,(FRandom[BigGun](-0.3,-0.2),FRandom[BigGun](0.4,0.5)),3,0,6,SWING_Spring,2,1.5);
UTMainHandler.DoSwing(self,(FRandom[BigGun](-0.3,-0.2),FRandom[BigGun](0.4,0.5)),3,0.5,7,SWING_Spring,3,1.5);
}
BIR2 NOP 2;
BIR2 Q 2
{
UTMainHandler.DoSwing(self,(FRandom[BigGun](0.2,0.3),FRandom[BigGun](-0.8,-1.2)),3,0,6,SWING_Spring,2,1.5);
UTMainHandler.DoSwing(self,(FRandom[BigGun](0.2,0.3),FRandom[BigGun](-0.8,-1.2)),3,-0.5,7,SWING_Spring,3,1.5);
}
BIR2 RSTUVWXYZ[\] 2;
BIR3 ABCDEF 2;
BIR3 A 2
{
UTMainHandler.DoSwing(self,(FRandom[BigGun](-0.3,-0.2),FRandom[BigGun](0.4,0.5)),2,-0.5,3,SWING_Spring,1,2.);
}
BIR3 BCDEF 2;
Goto Idle;
Deselect:
BIGD A 1

View file

@ -187,12 +187,12 @@ Class Bonesaw : UnrealWeapon
{
A_Overlay(-9999,"Null");
A_PlaySound("bonesaw/claw",CHAN_WEAPON,Dampener.Active(self)?.1:1.);
UTMainHandler.DoSwing(self,(FRandom[Bonesaw](-0.1,0.1),FRandom[Bonesaw](-0.2,-0.3)),4,0,8,SWING_Spring,5,0.7);
UTMainHandler.DoSwing(self,(FRandom[Bonesaw](-0.1,0.1),FRandom[Bonesaw](-0.2,-0.3)),4,0.2,8,SWING_Spring,2,2.);
}
CSWA ABC 2;
CSWA D 0
{
UTMainHandler.DoSwing(self,(FRandom[Bonesaw](-0.1,0.1),FRandom[Bonesaw](0.8,0.5)),2,0,8,SWING_Spring,2,1.2);
UTMainHandler.DoSwing(self,(FRandom[Bonesaw](-0.1,0.1),FRandom[Bonesaw](0.8,0.5)),6,-1,8,SWING_Spring,2,1.2);
}
CSWA DEF 1;
CSWA G 0 A_Clamp();

View file

@ -541,7 +541,7 @@ Class DispersionPistol : UnrealWeapon
}
A_OverlayFlags(PSP_FLASH,PSPF_RenderStyle,true);
A_OverlayRenderstyle(PSP_FLASH,STYLE_Add);
UTMainHandler.DoSwing(self,(FRandom[DPistol](-0.1,-0.3),FRandom[DPistol](-0.1,0.3)),2,-0.3,3,SWING_Spring,0,3);
UTMainHandler.DoSwing(self,(FRandom[DPistol](-0.1,-0.3),FRandom[DPistol](-0.1,0.3)),2+invoker.upgradelevel*0.5,-0.3,3,SWING_Spring,0,3+invoker.upgradelevel);
if ( !Dampener.Active(self) ) A_AlertMonsters();
A_QuakeEx(2,2,2,4,0,1,"",QF_RELATIVE|QF_SCALEDOWN,rollIntensity:0.1);
Vector3 x, y, z;
@ -614,7 +614,7 @@ Class DispersionPistol : UnrealWeapon
A_OverlayFlags(PSP_FLASH,PSPF_RenderStyle,true);
A_OverlayRenderstyle(PSP_FLASH,STYLE_Add);
double ss = 0.5+invoker.chargesize*0.3;
UTMainHandler.DoSwing(self,(FRandom[DPistol](-0.1,-0.3)*ss,FRandom[DPistol](-0.1,0.3))*ss,2,-0.3,3,SWING_Spring,0,3);
UTMainHandler.DoSwing(self,(FRandom[DPistol](-0.1,-0.3)*ss,FRandom[DPistol](-0.1,0.3))*ss,2+invoker.upgradelevel*0.5,-0.3,3,SWING_Spring,0,3+invoker.upgradelevel);
if ( !Dampener.Active(self) ) A_AlertMonsters();
int qs = int(1+invoker.chargesize*0.3);
A_QuakeEx(qs,qs,qs,4,0,1,"",QF_RELATIVE|QF_SCALEDOWN,rollIntensity:0.1);
@ -850,7 +850,7 @@ Class DispersionPistol : UnrealWeapon
Wait;
AltRelease2:
#### # 3 A_DispAltFire();
DPF2 ABC 6;
DPF2 ABC 8;
DPI2 A 3;
Goto Idle;
AltFire3:
@ -858,7 +858,7 @@ Class DispersionPistol : UnrealWeapon
Wait;
AltRelease3:
#### # 3 A_DispAltFire();
DPF3 ABC 6;
DPF3 ABC 9;
DPI3 A 3;
Goto Idle;
AltFire4:
@ -866,7 +866,7 @@ Class DispersionPistol : UnrealWeapon
Wait;
AltRelease4:
#### # 3 A_DispAltFire();
DPF4 ABC 6;
DPF4 ABC 10;
DPI4 A 3;
Goto Idle;
AltFire5:
@ -874,7 +874,7 @@ Class DispersionPistol : UnrealWeapon
Wait;
AltRelease5:
#### # 3 A_DispAltFire();
DPF5 ABC 6;
DPF5 ABC 12;
DPI5 A 3;
Goto Idle;
Upgrade:

View file

@ -384,7 +384,7 @@ Class FlameGun : UnrealWeapon
for ( int i=0; i<(bAlt?1:3); i++ )
{
a = FRandom[FlameGun](0,360);
s = FRandom[FlameGun](0,bAlt?0.:.15);
s = FRandom[FlameGun](0,bAlt?0.:.06);
dir = (x2+y2*cos(a)*s+z2*sin(a)*s).unit();
let p = Spawn(bAlt?"UFireball2":"UFireball",origin);
p.angle = atan2(dir.y,dir.x);

View file

@ -37,7 +37,7 @@ Class SMiniShell : FastProjectile
{
Obituary "$O_SMINI";
DamageType 'Shot';
DamageFunction 300;
DamageFunction 400;
Radius 4;
Height 4;
Speed 200;
@ -71,7 +71,7 @@ Class SMiniShell : FastProjectile
A_AlertMonsters();
A_SetRenderStyle(1.0,STYLE_Add);
A_NoGravity();
A_Explode(150,120,XF_HURTSOURCE|XF_EXPLICITDAMAGETYPE,damagetype:'exploded');
A_Explode(200,120,XF_HURTSOURCE|XF_EXPLICITDAMAGETYPE,damagetype:'exploded');
A_QuakeEx(4,4,4,10,0,250,"",QF_RELATIVE|QF_SCALEDOWN,falloff:120,rollintensity:0.2);
A_PlaySound("smini/explode",CHAN_VOICE,pitch:FRandom[SMini](0.8,1.2));
A_SprayDecal("SmallRocketBlast");
@ -214,7 +214,7 @@ Class SMiniGun : UnrealWeapon
for ( int i=0; i<(bAlt?4:1); i++ )
{
if ( bAlt && !weap.DepleteAmmo(weap.bAltFire,true,1) ) break;
UTMainHandler.DoSwing(self,basedir+(FRandom[SMini](-0.04,0.04),FRandom[SMini](-0.04,0.04)),FRandom[SMini](3,4),FRandom[SMini](-0.2,0.8),Random[SMini](2,4),SWING_Spring,Random[SMini](3,6),FRandom[SMini](1.5,2.3));
UTMainHandler.DoSwing(self,basedir+(FRandom[SMini](-0.04,0.04),FRandom[SMini](-0.04,0.04)),FRandom[SMini](6,8),FRandom[SMini](-1,-2),Random[SMini](3,4),SWING_Spring,Random[SMini](3,4),FRandom[SMini](2.2,3.5));
int pos = bAlt?i:invoker.special1;
origin = level.Vec3Offset(origin,x*(!(pos%2)?-1.5:1.5)+y*(pos<2?1.5:-1.5));
double a = FRandom[Minigun](0,360), s = FRandom[Minigun](0,bAlt?0.12:0.03);

View file

@ -125,6 +125,7 @@ Class ImpalerBoltTracer : LineTracer
{
Actor ignoreme;
Array<HitListEntry> hitlist;
Array<Line> ShootThroughList;
override ETraceStatus TraceCallback()
{
@ -145,6 +146,7 @@ Class ImpalerBoltTracer : LineTracer
{
if ( !Results.HitLine.sidedef[1] || (Results.HitLine.Flags&(Line.ML_BlockHitscan|Line.ML_BlockEverything)) )
return TRACE_Stop;
ShootThroughList.Push(Results.HitLine);
return TRACE_Skip;
}
return TRACE_Stop;
@ -167,7 +169,10 @@ Class ImpalerBurstBolt : Actor
t.hitlist.Clear();
Vector3 x, y, z;
[x, y, z] = dt_CoordUtil.GetAxes(pitch,angle,roll);
t.ShootThroughList.Clear();
t.Trace(pos,CurSector,x,11.125,0);
for ( int i=0; i<t.ShootThroughList.Size(); i++ )
t.ShootThroughList[i].Activate(target,0,SPAC_PCross);
for ( int i=0; i<t.hitlist.Size(); i++ )
{
UTMainHandler.DoKnockback(t.hitlist[i].hitactor,t.hitlist[i].x,6000);
@ -307,7 +312,10 @@ Class ImpalerBolt : Actor
t.HitList.Clear();
if ( bHITOWNER ) t.ignoreme = null;
else t.ignoreme = target;
t.ShootThroughList.Clear();
t.Trace(pos,cursector,x,beamsize,0);
for ( int i=0; i<t.ShootThroughList.Size(); i++ )
t.ShootThroughList[i].Activate(target,0,SPAC_PCross);
for ( int i=0; i<t.HitList.Size(); i++ )
{
if ( !(GetAge()%15) )

View file

@ -1365,13 +1365,24 @@ Class UFlashlight : UnrealInventory
Owner.A_PlaySound("lite/off",CHAN_ITEM);
if ( Owner.CheckLocalView() ) Console.Printf(StringTable.Localize("$D_FLASHLIGHT"));
if ( Amount <= 0 ) DepleteOrDestroy();
else
{
if ( lt[0] ) lt[0].Destroy();
if ( lt[1] ) lt[1].Destroy();
}
}
}
override void DetachFromOwner()
{
Super.DetachFromOwner();
if ( lt[0] ) lt[0].Destroy();
if ( lt[1] ) lt[1].Destroy();
Super.DetachFromOwner();
}
override void OwnerDied()
{
if ( lt[0] ) lt[0].Destroy();
if ( lt[1] ) lt[1].Destroy();
Super.OwnerDied();
}
override void Travelled()
{
@ -1413,6 +1424,11 @@ Class USearchlight : UFlashlight
Owner.A_PlaySound("lite/off",CHAN_ITEM);
if ( Owner.CheckLocalView() ) Console.Printf(StringTable.Localize("$D_SEARCHLIGHT"));
if ( Amount <= 0 ) DepleteOrDestroy();
else
{
if ( lt[0] ) lt[0].Destroy();
if ( lt[1] ) lt[1].Destroy();
}
}
}
override void SetupLights()

View file

@ -230,7 +230,7 @@ Class UFlame : Actor
override void PostBeginPlay()
{
Super.PostBeginPlay();
if ( waterlevel <= 0 )
if ( (waterlevel <= 0) && Random[FlameT](0,1) )
{
let l = Spawn("UFlameLight",pos);
l.target = self;
@ -262,18 +262,18 @@ Class UFlame : Actor
let s = Spawn("UTSmoke",pos);
s.vel = (FRandom[FlameT](-0.2,0.2),FRandom[FlameT](-0.2,0.2),FRandom[FlameT](-0.2,0.2));
s.vel += vel*0.3;
s.alpha *= alpha*2;
s.alpha *= alpha*4;
s.scale *= 0.5+abs(scale.x)*(.5+GetAge()/6.);
}
if ( bAMBUSH ) return;
if ( Random[FlameT](0,int(20*((default.alpha+0.1)-alpha))) ) return;
double rad = 60+60*int(0.4-alpha);
double rad = 60+120*int(0.2-alpha);
let bt = BlockThingsIterator.Create(self,rad);
while ( bt.Next() )
{
let t = bt.Thing;
if ( !t || !t.bSHOOTABLE || (t.Health <= 0) || (t == tracer) || ((t == master) && (GetAge() < 6)) || (Distance3D(t) > rad+t.radius) ) continue;
int amt = max(1,int(alpha*5));
int amt = max(1,int(alpha*10));
OnFire.Apply(t,master,amt);
}
}
@ -283,7 +283,7 @@ Class UFlame : Actor
Speed 20;
Radius 4;
Height 4;
Alpha 0.4;
Alpha 0.2;
Scale 0.1;
+NOBLOCKMAP;
+NOGRAVITY;
@ -304,7 +304,7 @@ Class UFlame : Actor
{
A_Flame();
A_SetScale(scale.x*1.01+0.04);
A_FadeOut(0.01);
A_FadeOut(0.005);
}
Stop;
}
@ -886,7 +886,7 @@ Class UFlamethrower : UnrealWeapon
Vector3 x, y, z, x2, y2, z2;
[x, y, z] = dt_CoordUtil.GetAxes(pitch,angle,roll);
Vector3 origin = level.Vec3Offset(Vec2OffsetZ(0,0,player.viewz),15*x+2.3*y-2.7*z);
//for ( int i=0; i<2; i++ )
for ( int i=0; i<2; i++ )
{
double a = FRandom[FlameT](0,360), s = FRandom[FlameT](0,.05);
[x2, y2, z2] = dt_CoordUtil.GetAxes(BulletSlope(),angle,roll);
@ -904,7 +904,7 @@ Class UFlamethrower : UnrealWeapon
p.vel = vel*.5+(cos(p.angle)*cos(p.pitch),sin(p.angle)*cos(p.pitch),-sin(p.pitch))*p.speed*FRandom[FlameT](0.3,0.6);
p.vel.z -= 3;
p.target = self;
//continue;
continue;
}
p.angle = atan2(dir.y,dir.x);
p.pitch = asin(-dir.z);

View file

@ -165,6 +165,7 @@ Class OLSMP : UnrealWeapon
Vector3 dir = (x2+y2*cos(a)*s+z2*sin(a)*s).unit();
FLineTraceData d;
LineTrace(atan2(dir.y,dir.x),10000,asin(-dir.z),TRF_ABSPOSITION,origin.z,origin.x,origin.y,d);
UTBulletTrail.DoTrail(self,origin,dir,10000,alt?6:4);
if ( d.HitType == TRACE_HitActor )
{
int dmg = 17;

View file

@ -105,6 +105,7 @@ Class PeaceRocket : Actor
while ( bi.Next() )
{
if ( !bi.Thing || (!bi.Thing.bISMONSTER && !bi.Thing.player) || (bi.Thing.Health <= 0) || (Distance3D(bi.Thing) > 500) || !CheckSight(bi.Thing) ) continue;
if ( sting_peacehome && ((bi.Thing == target) || (target && target.IsFriend(bi.Thing))) ) continue;
double dist = Distance3D(bi.Thing);
if ( dist > mindist ) break;
tracer = bi.Thing;
@ -185,6 +186,8 @@ Class PeaceRocket : Actor
A_CheckForTargets();
A_CountDown();
}
// early check
if ( GetAge() == 5 ) A_CheckForTargets();
}
Wait;
Death:

View file

@ -92,6 +92,7 @@ Class QCasing : UCasing
Class QuadshotTracer : LineTracer
{
Actor ignoreme;
Array<Line> ShootThroughList;
Array<HitListEntry> hitlist;
override ETraceStatus TraceCallback()
@ -123,6 +124,7 @@ Class QuadshotTracer : LineTracer
{
if ( !Results.HitLine.sidedef[1] || (Results.HitLine.Flags&(Line.ML_BlockHitscan|Line.ML_BlockEverything)) )
return TRACE_Stop;
ShootThroughList.Push(Results.HitLine);
return TRACE_Skip;
}
return TRACE_Stop;
@ -184,8 +186,16 @@ Class QuadShot : UnrealWeapon
return ClipOut?-1:ClipCount, -1, (ClipCount<2), false;
}
action void ProcessTraceHit( QuadshotTracer t )
action void ProcessTraceHit( QuadshotTracer t, Vector3 origin, Vector3 dir, int bc = 1 )
{
for ( int i=0; i<invoker.t.ShootThroughList.Size(); i++ )
invoker.t.ShootThroughList[i].Activate(self,0,SPAC_PCross);
for ( int i=5; i<invoker.t.Results.Distance; i+=10 )
{
if ( !Random[Boolet](0,4*bc) ) continue;
let b = Actor.Spawn("UTBubble",level.Vec3Offset(origin,dir*i));
b.Scale *= FRandom[Boolet](0.4,0.6);
}
for ( int i=0; i<t.HitList.Size(); i++ )
{
int dmg = 12;
@ -258,7 +268,7 @@ Class QuadShot : UnrealWeapon
for ( int i=0; i<invoker.clipcount; i++ )
{
for ( int i=0; i<3; i++ )
UTMainHandler.DoSwing(self,(FRandom[Quadshot](-0.04,-0.2),FRandom[Quadshot](-0.2,0.2)),FRandom[Quadshot](2,4),FRandom[Quadshot](-0.2,0.5),Random[Quadshot](3,4),SWING_Spring,Random[Quadshot](1,6),FRandom[Quadshot](0.8,1.4));
UTMainHandler.DoSwing(self,(FRandom[Quadshot](-0.04,-0.2),FRandom[Quadshot](-0.2,0.2)),FRandom[Quadshot](6,8),FRandom[Quadshot](-1.,-1.5),Random[Quadshot](6,8),SWING_Spring,0,FRandom[Quadshot](1.8,2.4));
for ( int i=0; i<10; i++ )
{
a = FRandom[Quadshot](0,360);
@ -267,8 +277,9 @@ Class QuadShot : UnrealWeapon
if ( !invoker.t ) invoker.t = new("QuadshotTracer");
invoker.t.ignoreme = self;
invoker.t.hitlist.Clear();
invoker.t.ShootThroughList.Clear();
invoker.t.Trace(origin,CurSector,dir,10000,0);
ProcessTraceHit(invoker.t);
ProcessTraceHit(invoker.t,origin,dir,int(spread));
}
}
vel += (0,0,(0.3+0.3*spread))-x*(1.5+1.1*spread);
@ -279,7 +290,7 @@ Class QuadShot : UnrealWeapon
A_QuakeEx(1,1,1,4,0,1,"",QF_RELATIVE|QF_SCALEDOWN,rollIntensity:0.12);
A_PlaySound("quadshot/fire",CHAN_WEAPON,!Dampener.Active(self)?1.:.2);
for ( int i=0; i<3; i++ )
UTMainHandler.DoSwing(self,(FRandom[Quadshot](-0.04,-0.2),FRandom[Quadshot](-0.2,0.2)),FRandom[Quadshot](2,3),FRandom[Quadshot](-0.2,0.5),Random[Quadshot](2,3),SWING_Spring,Random[Quadshot](0,3),FRandom[Quadshot](0.8,1.4));
UTMainHandler.DoSwing(self,(FRandom[Quadshot](-0.04,-0.2),FRandom[Quadshot](-0.2,0.2)),FRandom[Quadshot](5,7),FRandom[Quadshot](-1,-1.5),Random[Quadshot](3,6),SWING_Spring,0,FRandom[Quadshot](1.8,2.4));
for ( int i=0; i<10; i++ )
{
a = FRandom[Quadshot](0,360);
@ -288,8 +299,9 @@ Class QuadShot : UnrealWeapon
if ( !invoker.t ) invoker.t = new("QuadshotTracer");
invoker.t.ignoreme = self;
invoker.t.hitlist.Clear();
invoker.t.ShootThroughList.Clear();
invoker.t.Trace(origin,CurSector,dir,10000,0);
ProcessTraceHit(invoker.t);
ProcessTraceHit(invoker.t,origin,dir);
}
vel += (0,0,0.3)-x*1.5;
invoker.clipcount--;

View file

@ -146,7 +146,9 @@ Class URifle : UnrealWeapon
Vector3 origin = level.Vec3Offset(Vec2OffsetZ(0,0,player.viewz),10*x);
if ( !zoomed ) origin = level.Vec3Offset(origin,y*3-z*2);
FLineTraceData d;
LineTrace(angle,10000,BulletSlope(),TRF_ABSPOSITION,origin.z,origin.x,origin.y,d);
double pt = BulletSlope();
LineTrace(angle,10000,pt,TRF_ABSPOSITION,origin.z,origin.x,origin.y,d);
UTBulletTrail.DoTrail(self,origin,(cos(angle)*cos(pt),sin(angle)*cos(pt),-sin(pt)),10000,alt?3:1);
if ( d.HitType == TRACE_HitActor )
{
int dmg = 45;

View file

@ -275,7 +275,7 @@ Class TarydiumDebuff : Thinker
{
let b = victim.Spawn("TarydiumExplosion",victim.Vec3Offset(FRandom[Stinger](-victim.radius,victim.radius),FRandom[Stinger](-victim.radius,victim.radius),FRandom[Stinger](0,victim.height)));
b.target = instigator;
b.special1 = int(amount); // in Unreal this was capped to 10, which would make it deal barely any damage
b.special1 = int(min(amount,100)); // in Unreal this was capped to 10, which would make it deal barely any damage
b.scale *= .8+min(1.,amount*0.01);
amount = amount*0.9-10; // in Unreal this falls off linearly 10 points at a time, which can take very long at full charge
}

View file

@ -18,7 +18,13 @@ Class StunnerAmmo : Ammo
if ( rechargephase < 7 ) return;
rechargespeed = max(2.,.2*Amount);
rechargephase = 0;
Amount = min(Amount+1,MaxAmount);
if ( Amount >= MaxAmount ) return;
let sting = Owner.FindInventory("StingerAmmo");
if ( sting && (sting.Amount > 0) )
{
sting.Amount--;
Amount++;
}
}
override bool TryPickup( in out Actor toucher )
{
@ -72,6 +78,7 @@ Class StunLight : PaletteLight
Class StunTracer : LineTracer
{
Actor owner, ignore;
Array<Line> ShootThroughList;
override ETraceStatus TraceCallback()
{
@ -85,6 +92,7 @@ Class StunTracer : LineTracer
{
if ( !Results.HitLine.sidedef[1] || (Results.HitLine.Flags&(Line.ML_BlockHitscan|Line.ML_BlockEverything)) )
return TRACE_Stop;
ShootThroughList.Push(Results.HitLine);
return TRACE_Skip;
}
return TRACE_Stop;
@ -117,7 +125,10 @@ Class StunProj : Actor
}
// step trace
tracedir = (cos(angle)*cos(pitch),sin(angle)*cos(pitch),-sin(pitch));
t.ShootThroughList.Clear();
t.Trace(pos,cursector,tracedir,500,0);
for ( int i=0; i<t.ShootThroughList.Size(); i++ )
t.ShootThroughList[i].Activate(target,0,SPAC_PCross);
totaldist += t.Results.Distance;
// spawn particles
for ( int i=10; i<t.Results.Distance; i+=80 )

View file

@ -65,19 +65,20 @@ Class AsbestosSuit : UnrealArmor
Inventory.PickupSound "misc/suit";
Inventory.Icon "I_Suit";
}
override void AbsorbDamage( int damage, Name damageType, out int newdamage )
override void ModifyDamage( int damage, Name damageType, out int newdamage, bool passive, Actor inflictor, Actor source, int flags )
{
if ( (damageType == 'Fire') || (damageType == 'Ice') ) damage = newdamage = 0;
Super.AbsorbDamage(damage,damageType,newdamage);
if ( passive && (Amount > 0) && ((damageType == 'Fire') || (damageType == 'Ice')) )
newdamage = 0;
}
override void AttachToOwner( Actor other )
{
Super.AttachToOwner(other);
if ( sting_allsuits ) return;
// remove other suits
Inventory i = other.FindInventory("ToxinSuit");
if ( i ) other.RemoveInventory(i);
i = other.FindInventory("KevlarSuit");
if ( i ) other.RemoveInventory(i);
Super.AttachToOwner(other);
}
States
{
@ -101,14 +102,15 @@ Class ToxinSuit : UnrealArmor
Inventory.PickupSound "misc/suit";
Inventory.Icon "I_TSuit";
}
override void AbsorbDamage( int damage, Name damageType, out int newdamage )
override void ModifyDamage( int damage, Name damageType, out int newdamage, bool passive, Actor inflictor, Actor source, int flags )
{
if ( damageType == 'Slime' ) damage = newdamage = 0;
Super.AbsorbDamage(damage,damageType,newdamage);
if ( passive && (Amount > 0) && ((damageType == 'Slime') || (damageType == 'Poison')) )
newdamage = 0;
}
override void AttachToOwner( Actor other )
{
Super.AttachToOwner(other);
if ( sting_allsuits ) return;
// remove other suits
Inventory i = other.FindInventory("AsbestosSuit");
if ( i ) other.RemoveInventory(i);
@ -140,6 +142,7 @@ Class KevlarSuit : UnrealArmor
override void AttachToOwner( Actor other )
{
Super.AttachToOwner(other);
if ( sting_allsuits ) return;
// remove other suits
Inventory i = other.FindInventory("AsbestosSuit");
if ( i ) other.RemoveInventory(i);
@ -163,9 +166,13 @@ Class ShieldBelt : UnrealArmor
Owner.A_PlaySound("belt/absorb",CHAN_7);
UTMainHandler.DoFlash(Owner,Color(80,255,224,0),5);
}
int oldamt = amount;
Super.AbsorbDamage(damage,damageType,newdamage);
if ( (oldamt > 0) && (amount <= 0) && Owner.CheckLocalView() ) Console.Printf(StringTable.Localize("$D_SHIELDBELT"));
}
override void DepleteOrDestroy()
{
if ( (amount <= 0) && Owner.CheckLocalView() )
Console.Printf(StringTable.Localize("$D_SHIELDBELT"));
Super.DepleteOrDestroy();
}
Default
{
@ -202,11 +209,16 @@ Class PowerShield : UnrealArmor
Owner.A_PlaySound("belt/absorb",CHAN_7);
UTMainHandler.DoFlash(Owner,Color(80,224,0,255),5);
gothit = true;
damage = 0;
newdamage = 0;
}
int oldamt = amount;
amount = int.max; // blocks all damage
Super.AbsorbDamage(damage,damageType,newdamage);
amount = oldamt; // does not drain here
if ( damage > 0 ) newdamage = ApplyDamageFactors(GetClass(),damageType,damage,damage);
}
override void DepleteOrDestroy()
{
if ( (amount <= 0) && Owner.CheckLocalView() )
Console.Printf(StringTable.Localize("$D_POWERSHIELD"));
Super.DepleteOrDestroy();
}
override void Tick()
{
@ -218,11 +230,7 @@ Class PowerShield : UnrealArmor
gothit = false;
}
if ( !(level.maptime%15) && !sting_pshield ) amount--;
if ( amount <= 0 )
{
if ( Owner.CheckLocalView() ) Console.Printf(StringTable.Localize("$D_POWERSHIELD"));
DepleteOrDestroy();
}
if ( amount <= 0 ) DepleteOrDestroy();
}
Default
{

View file

@ -93,6 +93,7 @@ Class URocket : Actor
{
Vector3 InitialDir, Acceleration;
int ticcnt;
bool ringex;
Default
{
Obituary "$O_EIGHTBALL";
@ -152,6 +153,39 @@ Class URocket : Actor
s.vel = pvel;
s.scale *= FRandom[Eightball](0.9,2.7);
}
if ( !invoker.ringex ) return;
Actor r = Spawn("ASMDSBeamRing",pos);
Vector3 HitNormal = (cos(angle)*cos(pitch),sin(angle)*cos(pitch),-sin(pitch));
if ( BlockingLine ) HitNormal = (-BlockingLine.delta.y,BlockingLine.delta.x,0).unit();
else if ( BlockingFloor )
{
// find closest 3d floor for its normal
F3DFloor ff = null;
for ( int i=0; i<BlockingFloor.Get3DFloorCount(); i++ )
{
if ( !(BlockingFloor.Get3DFloor(i).top.ZAtPoint(pos.xy) ~== floorz) ) continue;
ff = BlockingFloor.Get3DFloor(i);
break;
}
if ( ff ) HitNormal = -ff.top.Normal;
else HitNormal = BlockingFloor.floorplane.Normal;
r.SetOrigin(r.Vec3Offset(0,0,2),false);
}
else if ( BlockingCeiling )
{
// find closest 3d floor for its normal
F3DFloor ff = null;
for ( int i=0; i<BlockingCeiling.Get3DFloorCount(); i++ )
{
if ( !(BlockingCeiling.Get3DFloor(i).bottom.ZAtPoint(pos.xy) ~== ceilingz) ) continue;
ff = BlockingCeiling.Get3DFloor(i);
break;
}
if ( ff ) HitNormal = -ff.bottom.Normal;
else HitNormal = BlockingCeiling.ceilingplane.Normal;
}
r.angle = atan2(HitNormal.y,HitNormal.x);
r.pitch = asin(-HitNormal.z);
}
action void A_RocketSeek()
{
@ -426,6 +460,8 @@ Class Eightball : UnrealWeapon
p.target = self;
p.tracer = invoker.LockedTarget;
a += step;
if ( !invoker.LockedTarget && (i==0) )
URocket(p).ringex = true;
}
}
else

View file

@ -47,12 +47,12 @@ Class UMinigun : UnrealWeapon
if ( alt )
{
A_QuakeEx(2,2,2,8,0,1,"",QF_RELATIVE|QF_SCALEDOWN,rollIntensity:0.12);
UTMainHandler.DoSwing(self,(FRandom[Minigun](-1,1),FRandom[Minigun](-1,1)),0.5,0,1,SWING_Spring,0,3);
UTMainHandler.DoSwing(self,(FRandom[Minigun](-1,1),FRandom[Minigun](-1,1)),0.5,0,2,SWING_Spring,0,3);
}
else
{
A_QuakeEx(1,1,1,8,0,1,"",QF_RELATIVE|QF_SCALEDOWN,rollIntensity:0.08);
UTMainHandler.DoSwing(self,(FRandom[Minigun](-1,1),FRandom[Minigun](-1,1)),0.3,0,1,SWING_Spring,0,3);
UTMainHandler.DoSwing(self,(FRandom[Minigun](-1,1),FRandom[Minigun](-1,1)),0.3,0,2,SWING_Spring,0,3);
}
let l = Spawn("MinigunLight",pos);
l.target = self;
@ -65,6 +65,7 @@ Class UMinigun : UnrealWeapon
Vector3 dir = (x2+y2*cos(a)*s+z2*sin(a)*s).unit();
FLineTraceData d;
LineTrace(atan2(dir.y,dir.x),10000,asin(-dir.z),TRF_ABSPOSITION,origin.z,origin.x,origin.y,d);
UTBulletTrail.DoTrail(self,origin,dir,10000,alt?5:3);
if ( d.HitType == TRACE_HitActor )
{
int dmg = Random[Minigun](8,14); // fun fact: the Minigun is one of the few weapons that has actual RNG damage in Unreal
@ -183,7 +184,8 @@ Class UMinigun : UnrealWeapon
let weap = Weapon(invoker);
if ( !(player.cmd.buttons&(BT_ATTACK|BT_ALTATTACK)) || (weap.Ammo1.Amount <= 0) )
{
player.SetPSprite(PSP_WEAPON,invoker.FindState("Release"));
A_StopSound(CHAN_WEAPON);
if ( Health > 0 ) player.SetPSprite(PSP_WEAPON,invoker.FindState("Release"));
return ResolveState("Null");
}
return ResolveState(null);

View file

@ -663,7 +663,7 @@ Class UnrealInventory : Inventory
{
Charge -= val;
if ( Charge > 0 ) return false;
if ( Amount > 1 )
if ( Amount >= 1 )
{
Amount--;
Charge = DefaultCharge;
@ -731,9 +731,15 @@ Class UnrealInventory : Inventory
}
override void DetachFromOwner()
{
Super.DetachFromOwner();
// deactivate
bActive = false;
Super.DetachFromOwner();
}
override void OwnerDied()
{
// deactivate
bActive = false;
Super.OwnerDied();
}
override void OnDrop( Actor dropper )
{

View file

@ -46,10 +46,15 @@ Class UInvisibility : UnrealInventory
DepleteOrDestroy();
}
}
override void OnDrop( Actor dropper )
override void DetachFromOwner()
{
Super.OnDrop(dropper);
dropper.TakeInventory("PowerUInvisibility",1);
Owner.TakeInventory("PowerUInvisibility",1);
Super.DetachFromOwner();
}
override void OwnerDied()
{
Owner.TakeInventory("PowerUInvisibility",1);
Super.OwnerDied();
}
override void PostBeginPlay()
{

View file

@ -120,6 +120,8 @@ Class UTranslocatorModule : Actor
{
SetOrigin(tracer.Vec2OffsetZ(0,0,pos.z),false);
vel.xy *= 0;
tracer = null;
bHITTRACER = false;
}
}
Stop;