diff --git a/cvarinfo.txt b/cvarinfo.txt index a63382d..8f98f81 100644 --- a/cvarinfo.txt +++ b/cvarinfo.txt @@ -84,3 +84,5 @@ server bool sting_bhold = false; // biorifle can be held fully loaded server bool sting_razoraim = false; // razorjack alt follows aim instead of // being steered by player rotation server bool sting_biosplash = false; // biorifle alt splashes like in ut +server bool sting_flametspread = false; // targets on fire spread the flames + // to anyone nearby (may be op) diff --git a/graphics/Sky95.png b/graphics/Sky95.png new file mode 100644 index 0000000..8708261 Binary files /dev/null and b/graphics/Sky95.png differ diff --git a/language.txt b/language.txt index 7d0ad8c..6680442 100644 --- a/language.txt +++ b/language.txt @@ -247,6 +247,7 @@ STING_QOPTS = "Convenience features"; STING_AUTOSCUBA = "Automatic SCUBA Gear toggling"; STING_RAZORAIM = "Razorjack altfire follows the crosshair"; STING_BIOSPLASH = "Biorifle altfire splashes like in UT"; +STING_FLAMETSPREAD = "Flamethrower fire spreads between targets"; STING_MCREDS = "Unreal Credits"; STING_CDR = "Doomreal"; STING_CLEAD = "Development Lead:"; @@ -483,6 +484,7 @@ STING_QOPTS = "Características de comodidad"; STING_AUTOSCUBA = "Uso automático de Kit de Buceo"; 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_MCREDS = "Créditos de Unreal"; STING_CDR = "Doomreal"; STING_CLEAD = "Desarrolladora Jefe:"; diff --git a/menudef.txt b/menudef.txt index bb6504f..68a913f 100644 --- a/menudef.txt +++ b/menudef.txt @@ -50,6 +50,7 @@ OptionMenu "UnrealOptionMenu" Option "$STING_AUTOSCUBA", "sting_autoscuba", "YesNo" Option "$STING_RAZORAIM", "sting_razoraim", "YesNo" Option "$STING_BIOSPLASH", "sting_biosplash", "YesNo" + Option "$STING_FLAMETSPREAD", "sting_flametspread", "YesNo" } AddOptionMenu "OptionsMenu" diff --git a/zscript/napalm.zsc b/zscript/napalm.zsc index 1c49bb3..443fea8 100644 --- a/zscript/napalm.zsc +++ b/zscript/napalm.zsc @@ -19,16 +19,263 @@ Class FlameAmmo : Ammo } } -Class UFlameTrail : Actor -{ -} - Class OnFire : Thinker { + Actor victim, instigator; + int amount, cnt; + + override void Tick() + { + if ( !victim ) + { + Destroy(); + return; + } + if ( victim.waterlevel > 0 ) + { + victim.A_RemoveLight('OnFireLight'); + amount -= victim.waterlevel**2; + } + else victim.A_AttachLight('OnFireLight',DynamicLight.RandomFlickerLight,Color(4,2,0)*clamp(amount,0,63),int(max(victim.radius,victim.height))+60+min(amount/4,40),int(max(victim.radius,victim.height))+60+min(amount/4,40)+8,DynamicLight.LF_ATTENUATE,(0,0,victim.height/2),0.1); + if ( victim.Health <= 0 ) amount = min(amount,100); + if ( !(level.maptime%3) ) + amount -= ((victim.Health>0)?1:2); + if ( amount < -10 ) + { + victim.A_RemoveLight('OnFireLight'); + Destroy(); + return; + } + if ( amount <= 0 ) return; + if ( cnt > 0 ) cnt--; + else + { + cnt = 10; + if ( victim.bSHOOTABLE && (victim.Health > 0) ) + victim.DamageMobj(instigator.FindInventory("UFlamethrower"),instigator,max(1,amount*(victim.bBOSS?0.05:0.15)),'Fire',DMG_THRUSTLESS); + if ( !victim ) + { + Destroy(); + return; + } + } + if ( level.maptime%5 ) return; + int numpt = clamp(int(Random[FlameT](2,4)*amount*0.02),1,4); + double mult = max(victim.radius,victim.height)/30.; + numpt = int(max(1,numpt*mult)); + for ( int i=0; i0); + } + return false; + } +} + +Class UFlameLight : PaletteLight +{ + Default + { + Tag "Ampd"; + Args 0,0,0,40; + ReactionTime 40; + } + override void Tick() + { + Super.Tick(); + Args[0] /= 5; + Args[1] /= 5; + Args[2] /= 5; + Args[3] += 4; + if ( !target || (target.waterlevel > 0) ) + { + Destroy(); + return; + } + SetOrigin(target.pos,true); + } +} +Class UFlameTrailLight : PaletteLight +{ + Default + { + Tag "Ampd"; + Args 0,0,0,80; + ReactionTime 20; + } + override void Tick() + { + Super.Tick(); + Args[0] /= 9; + Args[1] /= 9; + Args[2] /= 9; + if ( !target || (target.waterlevel > 0) ) + { + Destroy(); + return; + } + SetOrigin(target.pos,true); + } } Class UFlame : Actor { + override void PostBeginPlay() + { + Super.PostBeginPlay(); + let l = Spawn("UFlameLight",pos); + l.target = self; + Scale.x *= RandomPick[ExploS](-1,1); + Scale.y *= RandomPick[ExploS](-1,1); + } + bool TraceCheck( Actor other ) + { + Vector3 to; + double len; + FLineTraceData d; + to = level.Vec3Diff(pos,other.pos); + len = to.length(); + to /= len; + if ( !LineTrace(atan2(to.y,to.x),len,asin(-to.z),TRF_THRUACTORS) ) return true; + to = level.Vec3Diff(pos,other.Vec3Offset(0,0,other.height/2)); + len = to.length(); + to /= len; + if ( !LineTrace(atan2(to.y,to.x),len,asin(-to.z),TRF_THRUACTORS) ) return true; + to = level.Vec3Diff(pos,other.Vec3Offset(0,0,other.height)); + len = to.length(); + to /= len; + if ( !LineTrace(atan2(to.y,to.x),len,asin(-to.z),TRF_THRUACTORS) ) return true; + return false; + } + action void A_Flame() + { + if ( waterlevel > 0 ) + vel *= 0.9; + else + { + vel *= 0.98; + vel.z += 0.2; + } + if ( waterlevel > 0 ) bINVISIBLE = true; + if ( !Random[FlameT](0,int(30*(0.4-alpha))) && (!bINVISIBLE || (waterlevel > 0)) ) + { + let s = Spawn("UTSmoke",pos+vel); + s.vel = (FRandom[FlameT](-0.2,0.2),FRandom[FlameT](-0.2,0.2),FRandom[FlameT](-0.2,0.2)); + s.vel += vel*0.2; + s.alpha *= 0.4; + s.scale *= 2.5; + } + if ( bAMBUSH && !sting_flametspread ) return; + if ( Random[FlameT](0,int(12*(0.4-alpha))) ) return; + double rad = bAMBUSH?10:60; + if ( !bAMBUSH ) rad += 90*(0.4-alpha); + let bt = BlockThingsIterator.Create(self,rad+200); + while ( bt.Next() ) + { + let t = bt.Thing; + if ( !t || !t.bSHOOTABLE || (t.Health <= 0) || (t == tracer) || (!bAMBUSH && (t == master) && (GetAge() < 6)) || (Distance3D(t) > rad+t.radius) || !invoker.TraceCheck(t) ) continue; + int amt = max(1,int(alpha*15)); + if ( bAMBUSH && OnFire.IsOnFire(t) ) amt /= 2; + OnFire.Apply(t,master,amt); + } + } + Default + { + RenderStyle "Add"; + Speed 20; + Radius 4; + Height 4; + Alpha 0.4; + Scale 0.1; + +NOBLOCKMAP; + +NOGRAVITY; + +NOFRICTION; + +SLIDESONWALLS; + +ACTIVATEPCROSS; + +ACTIVATEIMPACT; + +NOTELEPORT; + +FORCEXYBILLBOARD; + +DROPOFF; + +NOBLOCKMONST; + } + States + { + Spawn: + SEXP AABBCCDDEEFFGGHHIIJJKKLLMMNNOOPPQQRRSSTT 1 Bright + { + A_Flame(); + A_SetScale(scale.x*1.08); + A_FadeOut(0.01); + } + Stop; + } +} + +Class UFlameTrail : UFlame +{ + override void PostBeginPlay() + { + Actor.PostBeginPlay(); + Scale.x *= RandomPick[ExploS](-1,1); + Scale.y *= RandomPick[ExploS](-1,1); + } + Default + { + Speed 2; + Alpha 0.3; + Scale 0.6; + +AMBUSH; + } + States + { + Spawn: + SEXP AABBCCDDEEFFGGHHIIJJKKLLMMNNOOPPQQRRSSTT 1 Bright + { + A_Flame(); + A_SetScale(scale.x*0.98); + A_FadeOut(0.01); + } + Stop; + } } Class UNapalm : Actor @@ -46,6 +293,13 @@ Class UFlamethrower : UnrealWeapon Owner.A_PlaySound("flamet/down",CHAN_6,Dampener.Active(self)?.1:1.); return Super.CreateTossable(amt); } + override void DoEffect() + { + Super.DoEffect(); + if ( Owner.player.ReadyWeapon != self ) return; + let psp = Owner.player.FindPSprite(-2); + if ( psp ) psp.alpha = (Owner.waterlevel>2)?.0:1.; + } action void A_FireFlame() { let weap = Weapon(invoker); @@ -60,6 +314,20 @@ Class UFlamethrower : UnrealWeapon weap.DepleteAmmo(weap.bAltFire,true,1); invoker.count -= 1.; } + invoker.FireEffect(); + A_AlertMonsters(); + UTMainHandler.DoFlash(self,Color(32,255,128,0),1); + 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),10*x+2.5*y-2*z); + Actor p = Spawn("UFlame",origin); + double a = FRandom[FlameT](0,360), s = FRandom[FlameT](0,.05); + [x2, y2, z2] = dt_CoordUtil.GetAxes(BulletSlope(),angle,roll); + Vector3 dir = (x2+y2*cos(a)*s+z2*sin(a)*s).unit(); + p.angle = atan2(dir.y,dir.x); + p.pitch = asin(-dir.z); + p.vel = vel*0.5+(cos(p.angle)*cos(p.pitch),sin(p.angle)*cos(p.pitch),-sin(p.pitch))*p.speed*FRandom[FlameT](0.8,1.4); + p.master = self; } action void A_BeginFlame() { @@ -121,6 +389,7 @@ Class UFlamethrower : UnrealWeapon Weapon.AmmoUse2 1; Weapon.AmmoGive 100; UTWeapon.DropAmmo 50; + +NOEXTREMEDEATH; } States { @@ -138,7 +407,7 @@ Class UFlamethrower : UnrealWeapon { A_PlaySound("flamet/idle",CHAN_6,Dampener.Active(self)?.1:1.,true); A_Overlay(-2,"FlameReady"); - A_OverlayFlags(-2,PSPF_RENDERSTYLE|PSPF_FORCESTYLE,true); + A_OverlayFlags(-2,PSPF_RENDERSTYLE|PSPF_FORCESTYLE|PSPF_ALPHA|PSPF_FORCEALPHA,true); A_OverlayRenderStyle(-2,STYLE_Add); } FLMS GHIJ 2 A_WeaponReady(WRF_NOFIRE); diff --git a/zscript/unrealcommon.zsc b/zscript/unrealcommon.zsc index 86aef70..633958d 100644 --- a/zscript/unrealcommon.zsc +++ b/zscript/unrealcommon.zsc @@ -1204,7 +1204,7 @@ Class UnrealMainHandler : EventHandler if ( (level.GetChecksum() ~== "959A613006CC3AA912C4A22908B7566A") || (level.GetChecksum() ~== "0EADB2F82732A968B8513E4DC6138439") ) { S_ChangeMusic("Cyrene"); - TextureID sky95 = TexMan.CheckForTexture("95Bg",TexMan.Type_Any); + TextureID sky95 = TexMan.CheckForTexture("Sky95",TexMan.Type_Any); level.ChangeSky(sky95,sky95); level.ReplaceTextures("rClfFlr0","C_flr19",0); level.ReplaceTextures("rClfBas0","C_wal19k",0);