Additional model progress.

Bump required version to 4.2.0.
Added Hexen style loading screen and other gameinfo stuff.
Small changes to fullscreen HUD.
Added 0.83 style status bar (incomplete).
Added player models.
Old file cleanup.
Ran all models through texnumsq, for convenience (skin indices are all over the place on some models).
PNG optimization pass.
This commit is contained in:
Marisa the Magician 2019-08-13 02:25:19 +02:00
commit 3a8925f3c0
178 changed files with 1887 additions and 356 deletions

0
zscript/biggun.zsc Normal file
View file

0
zscript/bonesaw.zsc Normal file
View file

0
zscript/flamegun.zsc Normal file
View file

View file

@ -1,195 +0,0 @@
// Unused dead code, kept for reference
// Tier 1 (chainsaw)
Class Tier1Weapon : RandomSpawner2 replaces Chainsaw
{
Default
{
DropItem "Stunner", 255;
DropItem "UnrealTranslocator", 255;
}
}
// Tier 2 (pistol, clip)
Class Tier2Weapon : RandomSpawner2 replaces Pistol
{
Default
{
DropItem "Automag", 255;
DropItem "OldAutomag", 255;
}
}
Class Tier2Ammo : RandomSpawner2 replaces Clip
{
Default
{
DropItem "UClip", 255;
}
}
// Tier 3 (shotgun, shells)
Class Tier3Weapon : RandomSpawner2 replaces Shotgun
{
Default
{
DropItem "Stinger", 255;
DropItem "ASMD", 255;
DropItem "Quadshot", 255;
DropItem "Impaler", 255;
}
}
Class Tier3Weapon2 : Tier3Weapon replaces SuperShotgun {}
Class Tier3Ammo : RandomSpawner2 replaces Shell
{
Default
{
DropItem "StingerAmmo", 255;
DropItem "ASMDAmmo", 255;
DropItem "QShells", 255;
}
}
Class Tier3Ammo2 : Tier3Ammo replaces ShellBox {}
// Tier 4 (chaingun, ammo box)
Class Tier4Weapon : RandomSpawner2 replaces Chaingun
{
Default
{
DropItem "Razorjack", 255;
DropItem "UMinigun", 255;
}
}
Class Tier4Ammo : RandomSpawner2 replaces ClipBox
{
Default
{
DropItem "RazorAmmo", 255;
DropItem "UMiniAmmo", 255;
}
}
// Tier 5 (rocket launcher, rocket ammo)
Class Tier5Weapon : RandomSpawner2 replaces RocketLauncher
{
Default
{
DropItem "Eightball", 255;
DropItem "UFlakCannon", 255;
}
}
Class Tier5Ammo : RandomSpawner2 replaces RocketAmmo
{
Default
{
DropItem "RocketCan", 255;
DropItem "UFlakAmmo", 255;
}
}
Class Tier5Ammo2 : RandomSpawner2 replaces RocketBox
{
Default
{
DropItem "RocketCan", 255;
DropItem "UFlakBox", 255;
}
}
// Tier 6 (plasma rifle, cell)
Class Tier6Weapon : RandomSpawner2 replaces PlasmaRifle
{
Default
{
DropItem "GESBioRifle", 255;
DropItem "Rifle", 255;
DropItem "Flamethrower", 255;
}
}
Class Tier6Ammo : RandomSpawner2 replaces Cell
{
Default
{
DropItem "BioSludge", 255;
DropItem "URifleShell", 255;
DropItem "NapalmCan", 255;
}
}
Class Tier6Ammo2 : RandomSpawner2 replaces CellPack
{
Default
{
DropItem "BioSludge", 255;
DropItem "URifleAmmo", 255;
DropItem "NapalmCan", 255;
}
}
// Tier 7 (bfg9000)
Class Tier7Weapon : RandomSpawner2 replaces BFG9000
{
Default
{
DropItem "GatlingGun", 255;
}
}
// Misc.
Class BerserkSpawner : RandomSpawner2 replaces Berserk
{
Default
{
DropItem "Amplifier", 255;
DropItem "WeaponPowerup", 255;
DropItem "UPowerup", 255;
}
}
Class LightSpawner : RandomSpawner2 replaces Infrared
{
Default
{
DropItem "Flashlight", 255;
DropItem "USearchlight", 255;
}
}
Class RadsuitSpawner : RandomSpawner2 replaces Radsuit
{
Default
{
DropItem "UJumpBoots", 255;
DropItem "ToxinSuit", 255;
}
}
Class BackpackSpawner : RandomSpawner2 replaces Backpack
{
Default
{
DropItem "AsbestosSuit", 255;
DropItem "VoiceBox", 255;
DropItem "ForceField", 255;
DropItem "UnrealBackpack", 255;
DropItem "MinigunSentry", 255;
DropItem "Peacemaker", 255;
}
}
Class BlursphereSpawner : RandomSpawner2 replaces Blursphere
{
Default
{
DropItem "UInvisibility", 255;
DropItem "Dampener", 255;
DropItem "ChameleonHeart", 255;
}
}
Class StimpakSpawner : RandomSpawner2 replaces Stimpack
{
Default
{
DropItem "Bandages", 255;
DropItem "NaliFruit", 255;
}
}

View file

@ -72,12 +72,20 @@ Class Stinger : UTWeapon
Weapon.AmmoGive 40;
UTWeapon.DropAmmo 20;
}
action void A_StingerFire()
action void A_StingerFire( bool hold = false )
{
Weapon weap = Weapon(invoker);
if ( !weap ) return;
if ( weap.Ammo1.Amount <= 0 ) return;
if ( !weap.DepleteAmmo(weap.bAltFire,true,1) ) return;
if ( hold ) A_Overlay(PSP_FLASH,"MFlashHold");
else
{
A_PlaySound("stinger/fire",CHAN_WEAPON);
A_Overlay(PSP_FLASH,"MFlash");
}
A_OverlayFlags(PSP_FLASH,PSPF_RenderStyle,true);
A_OverlayRenderstyle(PSP_FLASH,STYLE_Add);
UTMainHandler.DoFlash(self,Color(16,0,64,255),1);
UTMainHandler.DoSwing(self,(FRandom[Stinger](-0.1,-0.2),FRandom[Stinger](-0.1,0.1)),4,-1.5,2,SWING_Spring,2,2);
A_AlertMonsters();
@ -96,6 +104,10 @@ Class Stinger : UTWeapon
Weapon weap = Weapon(invoker);
if ( !weap ) return;
if ( weap.Ammo1.Amount <= 0 ) return;
A_PlaySound("stinger/altfire",CHAN_WEAPON);
A_Overlay(PSP_FLASH,"MFlash");
A_OverlayFlags(PSP_FLASH,PSPF_RenderStyle,true);
A_OverlayRenderstyle(PSP_FLASH,STYLE_Add);
UTMainHandler.DoFlash(self,Color(16,0,64,255),1);
UTMainHandler.DoSwing(self,(FRandom[Stinger](-0.3,-0.8),FRandom[Stinger](-0.4,0.4)),4,-1,3,SWING_Spring,3,5);
A_AlertMonsters();
@ -104,7 +116,6 @@ Class Stinger : UTWeapon
[x, y, z] = dt_Matrix4.GetAxes(pitch,angle,roll);
Vector3 origin = (pos.x,pos.y,player.viewz)+10.0*x+8.0*y-9.0*z;
[x, y, z] = dt_Matrix4.GetAxes(BulletSlope(),angle,roll);
A_PlaySound("stinger/altfire",CHAN_WEAPON);
Actor p;
double a, s;
Vector3 dir;
@ -142,14 +153,7 @@ Class Stinger : UTWeapon
}
Wait;
Fire:
STNF A 2
{
A_PlaySound("stinger/fire",CHAN_WEAPON);
A_StingerFire();
A_Overlay(PSP_FLASH,"MFlash");
A_OverlayFlags(PSP_FLASH,PSPF_RenderStyle,true);
A_OverlayRenderstyle(PSP_FLASH,STYLE_Add);
}
STNF A 2 A_StingerFire();
STNF BC 2;
STNI A 3;
STNI A 0 A_Refire(1);
@ -158,23 +162,17 @@ Class Stinger : UTWeapon
Hold:
STNH A 1
{
A_StingerFire();
A_Overlay(PSP_FLASH,"MFlashHold");
A_OverlayFlags(PSP_FLASH,PSPF_RenderStyle,true);
A_OverlayRenderstyle(PSP_FLASH,STYLE_Add);
// need to make sure player does the repeat fire anim
if ( self is 'UPlayer' )
UPlayer(self).PlayAttacking();
A_StingerFire(true);
}
STNH BCDEFG 1;
STNH A 0 A_Refire();
STNH A 2 A_PlaySound("stinger/release",CHAN_WEAPON);
Goto Idle;
AltFire:
STNF A 2
{
A_StingerAltFire();
A_Overlay(PSP_FLASH,"MFlash");
A_OverlayFlags(PSP_FLASH,PSPF_RenderStyle,true);
A_OverlayRenderstyle(PSP_FLASH,STYLE_Add);
}
STNF A 2 A_StingerAltFire();
STNF BC 2;
STNI A 35; // yes, 1 second cooldown
Goto Idle;

View file

@ -49,6 +49,36 @@ Class UFlakCannon : UTWeapon
if ( first ) A_PlaySound("flak/load",CHAN_WEAPON);
else A_PlaySound("flak/reload",CHAN_6);
}
action void A_FireChunks()
{
Weapon weap = Weapon(invoker);
if ( !weap ) return;
if ( weap.Ammo1.Amount <= 0 ) return;
if ( !weap.DepleteAmmo(weap.bAltFire,true,1) ) return;
A_PlaySound("flak/fire",CHAN_WEAPON);
A_Overlay(PSP_FLASH,"Flash");
A_OverlayFlags(PSP_FLASH,PSPF_RenderStyle,true);
A_OverlayRenderstyle(PSP_FLASH,STYLE_Add);
UTMainHandler.DoFlash(self,Color(48,255,96,0),1);
UTMainHandler.DoSwing(self,(FRandom[Flak](-0.3,-0.8),FRandom[Flak](-0.5,0.5)),4,-1.5,2,SWING_Spring,2,2);
A_AlertMonsters();
A_QuakeEx(1,1,1,3,0,1,"",QF_RELATIVE|QF_SCALEDOWN,rollIntensity:0.05);
}
action void A_FireSlug()
{
Weapon weap = Weapon(invoker);
if ( !weap ) return;
if ( weap.Ammo1.Amount <= 0 ) return;
if ( !weap.DepleteAmmo(weap.bAltFire,true,1) ) return;
A_PlaySound("flak/altfire",CHAN_WEAPON);
A_Overlay(PSP_FLASH,"AltFlash");
A_OverlayFlags(PSP_FLASH,PSPF_RenderStyle,true);
A_OverlayRenderstyle(PSP_FLASH,STYLE_Add);
UTMainHandler.DoFlash(self,Color(32,255,96,0),1);
UTMainHandler.DoSwing(self,(FRandom[Flak](-0.4,-0.8),FRandom[Flak](0.4,0.8)),4,-1,3,SWING_Spring,3,5);
A_AlertMonsters();
A_QuakeEx(2,2,2,6,0,1,"",QF_RELATIVE|QF_SCALEDOWN,rollIntensity:0.1);
}
Default
{
Tag "$T_FLAKCANNON";
@ -91,23 +121,17 @@ Class UFlakCannon : UTWeapon
FLKI A 1 A_WeaponReady();
Wait;
Fire:
FLKF A 1
{
A_Overlay(PSP_FLASH,"Flash");
A_OverlayFlags(PSP_FLASH,PSPF_RenderStyle,true);
A_OverlayRenderstyle(PSP_FLASH,STYLE_Add);
}
FLKF BCDEFGHIJ 1;
FLKE ABCDEFGHIJKLMNS 1;
FLKF A 1 A_FireChunks();
FLKF BCDEFGHI 1;
FLKF J 5;
FLKE A 1 A_PlaySound("flak/click",CHAN_6);
FLKE BCDEFGHIJKLMN 1;
FLKE S 4;
Goto Loading;
AltFire:
FLKA A 2
{
A_Overlay(PSP_FLASH,"AltFlash");
A_OverlayFlags(PSP_FLASH,PSPF_RenderStyle,true);
A_OverlayRenderstyle(PSP_FLASH,STYLE_Add);
}
FLKA BCDEFGHIJK 2;
FLKA A 1 A_FireSlug();
FLKA BCDEFGHIJK 1;
FLKA K 10;
Goto Loading;
Deselect:
FLKD A 0 A_JumpIfNoAmmo("Deselect2");
@ -122,7 +146,7 @@ Class UFlakCannon : UTWeapon
FLFF ABCDEFGHIJ 1 Bright;
Stop;
AltFlash:
FLFA ABCDEFGHIJK 2 Bright;
FLFA ABCDEF 1 Bright;
Stop;
}
}

View file

@ -156,57 +156,318 @@ Class UPlayer : UTPlayer
}
else GiveInventory(type,amount,true);
}
override void PlayAttacking()
{
// no animation if crouched
if ( (player && (player.mo == self)) && (player.crouchdir == -1) ) return;
// check weapon type
let psp = player.FindPSprite(PSP_WEAPON);
if ( (player.ReadyWeapon is 'Stinger') && psp
&& psp.CurState.InStateSequence(player.ReadyWeapon.FindState("Hold")) )
{
if ( !InStateSequence(CurState,FindState("MissileRep")) )
SetStateLabel("MissileRep");
}
else SetStateLabel("Missile");
}
}
Class UPlayerFemale1 : UPlayer
Class UFemaleArmGibber : UTGibber
{
bool firstgib;
override void BurstGibs()
{
Actor a;
double ang, pt;
Vector3 dir;
if ( !firstgib )
{
firstgib = true;
Actor a = Spawn("UTFemaleArm",Vec3Offset(-14*sin(angle),14*cos(angle),36));
ang = FRandom[Blod](0,360);
pt = FRandom[Blod](-90,90);
dir = (cos(pt)*cos(ang),cos(pt)*sin(ang),sin(-pt));
a.vel = rvel*0.6+dir*FRandom[Blod](3.0,6.0);
}
for ( int i=0; i<gibsize; i++ )
{
Vector3 box = (FRandom[Blod](-4,4),FRandom[Blod](12,18),FRandom[Blod](32,40));
let a = Spawn("UTBloodPuff",Vec3Offset(box.x*cos(angle)-box.y*sin(angle),box.x*sin(angle)+box.y*cos(angle),box.z));
ang = FRandom[Blod](0,360);
pt = FRandom[Blod](-90,90);
dir = (cos(pt)*cos(ang),cos(pt)*sin(ang),sin(-pt));
a.vel = rvel*0.2+dir*FRandom[Blod](1.5,3.0);
}
A_CountDown();
}
override void PostBeginPlay()
{
Super.PostBeginPlay();
gibsize = 3;
reactiontime = 5;
}
States
{
Spawn:
TNT1 A 0 NoDelay; // no sound, done by player
TNT1 A 1 BurstGibs();
Wait;
}
}
Class UPlayerFemale : UPlayer
{
Default
{
Player.SoundClass "ufemale";
UTPlayer.VoiceType VOICE_FemaleOne;
}
void A_ArmPop()
{
armlessL = true;
let a = Actor.Spawn("UFemaleArmGibber",pos);
a.vel = vel;
a.Scale = Scale;
a.A_SetSize(radius,height);
UTGibber(a).Gibbed = self;
}
States
{
Reload:
#### # 3;
PLYR ABCDEF 4;
Goto Spawn;
Death.Zapped:
#### # 0;
Goto Death;
Death.Decapitated:
#### # 0 A_HeadPop();
PLD6 A 3 A_PlayerScream();
PLD6 B 3 A_NoBlocking();
PLD6 CDEFGHIJ 3;
PLD6 K 1 A_DMFade();
Wait;
Death:
#### # 0 A_JumpIf(Health<(GetGibHealth()/3),"Death7");
#### # 0 A_JumpIf(vel.length()>20,"Death2");
#### # 0 A_JumpIf(vel.length()>10,"Death5");
#### # 0 A_Jump(256,"Death1","Death3","Death4");
Death1:
#### # 3;
PLD1 A 3 A_PlayerScream();
PLD1 B 3 A_NoBlocking();
PLD1 CDEFGHIJKLMNOPQRSTU 3;
PLD1 V 1 A_DMFade();
Wait;
Death2:
#### # 3;
PLD2 A 3 A_PlayerScream();
PLD2 B 3 A_NoBlocking();
PLD2 CDEFGHIJKLMNOPQ 3;
PLD2 R 1 A_DMFade();
Wait;
Death3:
#### # 3;
PLD3 A 3 A_PlayerScream();
PLD3 B 3 A_NoBlocking();
PLD3 CDEFGHIJKLMNO 3;
PLD3 P 1 A_DMFade();
Wait;
Death4:
#### # 3;
PLD4 A 3 A_PlayerScream();
PLD4 B 3 A_NoBlocking();
PLD4 CDEFGHIJKL 3;
PLD4 M 1 A_DMFade();
Wait;
Death5:
#### # 3;
PLD5 A 3 A_PlayerScream();
PLD5 B 3 A_NoBlocking();
PLD5 CDEFGHIJKLMNO 3;
PLD5 P 1 A_DMFade();
Wait;
Death7:
#### # 0 A_ArmPop();
PLD7 A 3 A_PlayerScream();
PLD7 B 3 A_NoBlocking();
PLD7 CDEFGHIJKLMNOPQRSTUV 3;
PLD7 W 1 A_DMFade();
Wait;
Taunt1:
#### # 5;
PLT1 ABCDEFGHIJKLMNO 3;
Goto Spawn+1;
Taunt2:
#### # 5;
PLT2 ABCDEFGHIJKLMNOPQR 4;
Goto Spawn+1;
Taunt3:
#### # 5;
PLT3 ABCDEFGHIJKLMNO 3;
Goto Spawn+1;
Taunt4:
#### # 0;
Goto Spawn;
}
}
Class UPlayerFemale1 : UPlayerFemale
{
Default
{
Player.DisplayName "$N_FEMALE1";
Player.Portrait "";
UTPlayer.VoiceType VOICE_FemaleTwo;
-NOMENU;
}
}
Class UPlayerFemale2 : UPlayer
Class UPlayerFemale2 : UPlayerFemale
{
Default
{
Player.SoundClass "ufemale";
Player.DisplayName "$N_FEMALE2";
Player.Portrait "";
UTPlayer.VoiceType VOICE_FemaleOne;
-NOMENU;
}
}
Class UPlayerMale1 : UPlayer
Class UMaleTorsoGibber : UTGibber
{
bool firstgib;
override void BurstGibs()
{
static const class<Actor> parts[] = {"UTMaleArm","UTMaleArm","UTMaleTorso","UTHeadMale","UTHeart","UTLiver","UTStomach"};
static const double partofsy[] = {14,-14,0,0,-2,5,-3};
static const double partofsz[] = {36,36,32,48,40,32,35};
Actor a;
double ang, pt;
Vector3 dir;
if ( !firstgib )
{
firstgib = true;
for ( int i=0; i<7; i++ )
{
Actor a = Spawn(parts[i],Vec3Offset(-partofsy[i]*sin(angle),partofsy[i]*cos(angle),partofsz[i]));
ang = FRandom[Blod](0,360);
pt = FRandom[Blod](-90,90);
dir = (cos(pt)*cos(ang),cos(pt)*sin(ang),sin(-pt));
a.vel = rvel*0.6+dir*FRandom[Blod](3.0,6.0);
}
}
for ( int i=0; i<gibsize; i++ )
{
Vector3 box = (FRandom[Blod](-15,15),FRandom[Blod](15,15),FRandom[Blod](30,50));
let a = Spawn("UTBloodPuff",Vec3Offset(box.x*cos(angle)-box.y*sin(angle),box.x*sin(angle)+box.y*cos(angle),box.z));
ang = FRandom[Blod](0,360);
pt = FRandom[Blod](-90,90);
dir = (cos(pt)*cos(ang),cos(pt)*sin(ang),sin(-pt));
a.vel = rvel*0.2+dir*FRandom[Blod](1.5,3.0);
}
A_CountDown();
}
override void PostBeginPlay()
{
Super.PostBeginPlay();
gibsize = 3;
reactiontime = 5;
}
States
{
Spawn:
TNT1 A 0 NoDelay; // no sound, done by player
TNT1 A 1 BurstGibs();
Wait;
}
}
Class UPlayerMale : UPlayer
{
Default
{
Player.SoundClass "umale";
UTPlayer.VoiceType VOICE_MaleOne;
}
void A_TorsoPop()
{
headless = true;
armlessL = true;
armlessR = true;
torsoless = true;
let a = Actor.Spawn("UMaleTorsoGibber",pos);
a.vel = vel;
a.Scale = Scale;
a.A_SetSize(radius,height);
UTGibber(a).Gibbed = self;
}
States
{
Death:
#### # 0 A_JumpIf(Health<(GetGibHealth()/3),"Death5");
#### # 0 A_JumpIf(vel.length()>20,"Death6");
#### # 0 A_JumpIf(vel.length()>10,"Death1");
#### # 0 A_Jump(256,"Death2","Death3","Death7");
Death5:
#### # 0 A_TorsoPop();
PLD5 A 3 A_PlayerScream();
PLD5 B 3 A_NoBlocking();
PLD5 CDEFGHIJKLMNOPQRSTUV 3;
PLD5 W 1 A_DMFade();
Wait;
Death6:
#### # 3;
PLD6 A 3 A_PlayerScream();
PLD6 B 3 A_NoBlocking();
PLD6 CDEFGHIJKLMNOPQRSTUVWXYZ[ 3;
PLD6 \ 1 A_DMFade();
Wait;
Taunt1:
#### # 5;
PLT1 ABCDEFG 6;
Goto Spawn+1;
Taunt2:
#### # 5;
PLT2 ABCDEFGHIJKLMNOPQRSTUVWXY 3;
Goto Spawn+1;
Taunt3:
#### # 5;
PLT3 ABCDEFGHIJKLMNO 3;
Goto Spawn+1;
Taunt4:
#### # 0;
Goto Spawn;
}
}
Class UPlayerMale1 : UPlayerMale
{
Default
{
Player.DisplayName "$N_MALE1";
Player.Portrait "";
UTPlayer.VoiceType VOICE_MaleOne;
-NOMENU;
}
}
Class UPlayerMale2 : UPlayer
Class UPlayerMale2 : UPlayerMale
{
Default
{
Player.SoundClass "umale";
Player.DisplayName "$N_MALE2";
Player.Portrait "";
UTPlayer.VoiceType VOICE_MaleOne;
-NOMENU;
}
}
Class UPlayerMale3 : UPlayer
Class UPlayerMale3 : UPlayerMale
{
Default
{
Player.SoundClass "umale";
Player.DisplayName "$N_MALE3";
Player.Portrait "";
UTPlayer.VoiceType VOICE_MaleTwo;
@ -282,12 +543,8 @@ Class UnrealStaticHandler : StaticEventHandler
else mtics++;
}
override void RenderOverlay( RenderEvent e )
override void RenderUnderlay( RenderEvent e )
{
// we have to stand in for the UT handler on this function
// although it doesn't make much sense yet
if ( players[consoleplayer].camera.player && players[consoleplayer].camera.player.ReadyWeapon && (players[consoleplayer].camera.player.ReadyWeapon is 'UTWeapon') )
UTWeapon(players[consoleplayer].camera.player.ReadyWeapon).RenderOverlay(e);
if ( gamestate != GS_TITLELEVEL ) return;
double ar = Screen.GetAspectRatio();
Vector2 tsize = TexMan.GetScaledSize(tex[cur+3]);
@ -307,6 +564,14 @@ Class UnrealStaticHandler : StaticEventHandler
double alf = clamp(((mtics+e.FracTic)/Thinker.TICRATE)-8,0.,1.);
Screen.DrawTexture(tex[cur],false,(vsize.x-tsize.x)/2,(vsize.y-tsize.y)/2,DTA_VirtualWidthF,vsize.x,DTA_VirtualHeightF,vsize.y,DTA_KeepRatio,true,DTA_Alpha,alf);
}
override void RenderOverlay( RenderEvent e )
{
// we have to stand in for the UT handler on this function
// although it doesn't make much sense yet
if ( players[consoleplayer].camera.player && players[consoleplayer].camera.player.ReadyWeapon && (players[consoleplayer].camera.player.ReadyWeapon is 'UTWeapon') )
UTWeapon(players[consoleplayer].camera.player.ReadyWeapon).RenderOverlay(e);
}
}
Class UnrealMainHandler : EventHandler

View file

@ -16,13 +16,16 @@ Class UnrealHUD : BaseStatusBar
int lastseentic, Count;
// Fonts
Font LargeFont, LargeRedFont, MedFont, WhiteFont, TinyFont,
TinyWhiteFont, TinyRedFont;
Font LargeFont, LargeRedFont, MedFont, WhiteFont, TinyFont, TinyWhiteFont, TinyRedFont;
HUDFont mMapFont;
// Common Textures
TextureID HalfHud, HudLine, HudAmmo, IconHeal, IconSkul, IconSel,
IconBase;
TextureID HalfHud, HudLine, HudAmmo, IconHeal, IconSkul, IconSel, IconBase;
// 0.83 HUD stuff
String OldAmmo[32];
Class<Ammo> OldAmmoType[32];
HUDFont mOldDigits;
// Translations
int RedIcon;
@ -30,7 +33,7 @@ Class UnrealHUD : BaseStatusBar
override void Init()
{
Super.Init();
SetSize(0,320,200);
SetSize(64,640,400);
// Initialize
Count = 0;
vtracer = new("ViewTracer");
@ -54,6 +57,11 @@ Class UnrealHUD : BaseStatusBar
IconSel = TexMan.CheckForTexture("IconSel",TexMan.Type_Any);
IconBase = TexMan.CheckForTexture("IconBase",TexMan.Type_Any);
RedIcon = Translation.GetID('RedIcon');
mOldDigits = HUDFont.Create(Font.FindFont('U083Digits'),26,Mono_CellLeft);
OldAmmo[0] = "Clip083";
OldAmmo[1] = "Shell083";
OldAmmo[2] = "Tary083";
OldAmmoType[2] = "StingerAmmo";
}
override void Draw( int state, double TicFrac )
@ -61,8 +69,7 @@ Class UnrealHUD : BaseStatusBar
Super.Draw(state,TicFrac);
HudMode = CVar.GetCVar('stinger_hudmode',players[consoleplayer]).GetInt();
scalev.x = scalev.y = Max(0,CVar.GetCVar('stinger_hudscale',players[consoleplayer]).GetInt());
if ( scalev.x == 0 )
scalev.x = scalev.y = max(1,min(Screen.GetWidth()/640.,Screen.GetHeight()/480.));
if ( scalev.x == 0 ) scalev.x = scalev.y = max(1,min(Screen.GetWidth()/640.,Screen.GetHeight()/480.));
ClipX = Screen.GetWidth()/scalev.x;
ClipY = Screen.GetHeight()/scalev.y;
CurX = 0;
@ -73,7 +80,13 @@ Class UnrealHUD : BaseStatusBar
UnrealInventory(i).PreRender(lbottom);
if ( CPlayer.ReadyWeapon is 'UTWeapon' )
UTWeapon(CPlayer.ReadyWeapon).PreRender(lbottom);
if ( (state == HUD_StatusBar) || (state == HUD_Fullscreen) )
if ( state == HUD_StatusBar )
{
BeginStatusBar();
FracTic = TicFrac;
DrawUnrealBar();
}
else if ( state == HUD_Fullscreen )
{
BeginHUD();
FracTic = TicFrac;
@ -145,14 +158,14 @@ Class UnrealHUD : BaseStatusBar
Screen.DrawText(TinyWhiteFont,Font.CR_UNTRANSLATED,CurX,CurY,score,DTA_VirtualWidthF,ClipX,DTA_VirtualHeightF,ClipY,DTA_KeepRatio,true);
}
private void DrawInventory( double x, double y, bool bDrawOne )
private void DrawInventory( double x, double y, bool bDrawOne = false, bool bNoWeapons = false )
{
bool bGotNext, bGotPrev, bGotSelected, bRed, bFlashTranslator;
Inventory Inv, Prev, Next, SelectedItem;
UTranslator translator;
double HalfHUDX, HalfHUDY;
double AmmoBarSize;
if ( HudMode < 4 ) // then draw HalfHUD
if ( (HudMode < 4) && !bNoWeapons ) // then draw HalfHUD
{
HalfHUDX = ClipX-64;
HalfHUDY = ClipY-32;
@ -194,71 +207,81 @@ Class UnrealHUD : BaseStatusBar
// drawing weapon slots differently than Unreal 1 because we have better methods here
let cw = CPlayer.ReadyWeapon;
int cwslot = -1;
if ( cw && (cw.SlotNumber != -1) ) cwslot = cw.SlotNumber?(cw.SlotNumber-1):9;
if ( cw && (cw.SlotNumber != -1) ) cwslot = cw.SlotNumber;
let pw = CPlayer.PendingWeapon;
int pwslot = -1;
if ( pw && (pw != WP_NOCHANGE) && (pw.SlotNumber != -1) ) pwslot = pw.SlotNumber?(pw.SlotNumber-1):9;
Weapon wslots[10];
// zero-initialize, fixes asmjit crash
for ( int i=0; i<10; i++ )
wslots[i] = null;
if ( pw && (pw != WP_NOCHANGE) && (pw.SlotNumber != -1) ) pwslot = pw.SlotNumber;
Array<Weapon> wslots[10];
// clear the arrays before work
for ( int i=0; i<10; i++ ) wslots[i].Clear();
// first run, populate the full array of weapons
for ( int i=0; i<10; i++ )
{
int sslot = (i<9)?(i+1):0;
for ( Inv = CPlayer.mo.Inv; Inv; Inv=Inv.Inv )
{
if ( !(Inv is 'Weapon') ) continue;
let w = Weapon(Inv);
if ( w.SlotNumber != sslot ) continue;
int slot = w.SlotNumber?(w.SlotNumber-1):9;
if ( !wslots[slot] )
if ( w.SlotNumber != i ) continue;
int slot = w.SlotNumber;
wslots[slot].Push(w);
}
}
// second run, sort the slot arrays
for ( int i=0; i<10; i++ )
{
int j = 1;
while ( j < wslots[i].Size() )
{
int k = j;
while ( (k > 0) && (wslots[i][k-1].SelectionOrder >= wslots[i][k].SelectionOrder) )
{
wslots[slot] = w;
continue;
Weapon tmp = wslots[i][k];
wslots[i][k] = wslots[i][k-1];
wslots[i][k-1] = tmp;
k--;
}
if ( (wslots[slot] == pw) || (wslots[slot] == cw) ) continue;
if ( (w == pw) || (w == cw) )
{
wslots[slot] = w;
continue;
}
if ( (w.SelectionOrder < wslots[slot].SelectionOrder) && (!w.Ammo1 || (w.Ammo1.Amount > 0)) )
wslots[slot] = w;
else if ( (w.SelectionOrder >= wslots[slot].SelectionOrder) && wslots[slot].Ammo1 && (wslots[slot].Ammo1.Amount <= 0) )
wslots[slot] = w;
j++;
}
}
// draw the slots
if ( HudMode < 4 )
if ( (HudMode < 4) && !bNoWeapons )
{
for ( int i=0; i<10; i++ )
{
if ( !wslots[i] ) continue;
if ( wslots[i].Size() <= 0 ) continue;
Font cfont = TinyFont;
if ( cwslot == i ) cfont = TinyWhiteFont;
int realslot = (i<9)?(i+1):9;
int realslot = i?i:10;
CurX = HalfHUDX-3+realslot*6;
CurY = HalfHUDY+4;
Screen.DrawText(cfont,Font.CR_UNTRANSLATED,CurX,CurY,String.Format("%d",realslot),DTA_VirtualWidthF,ClipX,DTA_VirtualHeightF,ClipY,DTA_KeepRatio,true);
// Draw ammo bar
let amo = wslots[i].Ammo1;
if ( !amo ) continue;
CurY = HalfHUDY+11;
AmmoBarSize = 16*min(1.0,amo.Amount/double(amo.MaxAmount));
CurY = HalfHUDY+29-AmmoBarSize;
if ( (AmmoBarSize < 8) && (amo.Amount < 10) && (amo.Amount > 0) )
Screen.DrawText(cfont,Font.CR_UNTRANSLATED,CurX,CurY,String.Format("%d",i),DTA_VirtualWidthF,ClipX,DTA_VirtualHeightF,ClipY,DTA_KeepRatio,true);
// Draw ammo bar(s)
int nammo = 0;
for ( int j=0; j<wslots[i].Size(); j++ ) if ( wslots[i][j].Ammo1 ) nammo++;
if ( nammo <= 0 ) continue;
int cbar = 0;
for ( int j=0; j<wslots[i].Size(); j++ )
{
CurY -= 9;
Screen.DrawText(TinyRedFont,Font.CR_UNTRANSLATED,CurX,CurY,String.Format("%d",amo.Amount),DTA_VirtualWidthF,ClipX,DTA_VirtualHeightF,ClipY,DTA_KeepRatio,true);
CurY += 9;
}
DrawColor = "00 FF 00";
if ( AmmoBarSize < 8 ) DrawColor = Color(255-int(AmmoBarSize)*30,int(AmmoBarSize)*30+40,0);
if ( amo.Amount > 0 )
{
Screen.DrawTexture(HudAmmo,false,CurX,CurY,DTA_VirtualWidthF,ClipX,DTA_VirtualHeightF,ClipY,DTA_KeepRatio,true,DTA_FillColor,BlackColor,DTA_DestWidth,4,DTA_DestHeightF,AmmoBarSize);
Screen.DrawTexture(HudAmmo,false,CurX,CurY,DTA_VirtualWidthF,ClipX,DTA_VirtualHeightF,ClipY,DTA_KeepRatio,true,DTA_AlphaChannel,true,DTA_FillColor,DrawColor,DTA_DestWidth,4,DTA_DestHeightF,AmmoBarSize);
let amo = wslots[i][j].Ammo1;
if ( !amo ) continue;
AmmoBarSize = 16*min(1.0,amo.Amount/double(amo.MaxAmount));
CurX = HalfHUDX-3+realslot*6+(4./nammo)*cbar;
CurY = HalfHUDY+29-AmmoBarSize;
if ( (AmmoBarSize < 8) && (amo.Amount < 10) && (amo.Amount > 0) && (nammo == 1) )
{
CurY -= 9;
Screen.DrawText(TinyRedFont,Font.CR_UNTRANSLATED,CurX,CurY,String.Format("%d",amo.Amount),DTA_VirtualWidthF,ClipX,DTA_VirtualHeightF,ClipY,DTA_KeepRatio,true);
CurY += 9;
}
DrawColor = Color(0,255,0);
if ( AmmoBarSize < 8 ) DrawColor = Color(255-int(AmmoBarSize)*30,int(AmmoBarSize)*30+40,0);
if ( wslots[i][j] != cw ) DrawColor = Color(DrawColor.r/2,DrawColor.g/2,DrawColor.b/2);
if ( amo.Amount > 0 )
{
Screen.DrawTexture(HudAmmo,false,CurX,CurY,DTA_VirtualWidthF,ClipX,DTA_VirtualHeightF,ClipY,DTA_KeepRatio,true,DTA_FillColor,BlackColor,DTA_DestWidthF,4./nammo,DTA_DestHeightF,AmmoBarSize);
Screen.DrawTexture(HudAmmo,false,CurX,CurY,DTA_VirtualWidthF,ClipX,DTA_VirtualHeightF,ClipY,DTA_KeepRatio,true,DTA_AlphaChannel,true,DTA_FillColor,DrawColor,DTA_DestWidthF,4./nammo,DTA_DestHeightF,AmmoBarSize);
}
cbar++;
}
}
}
@ -294,7 +317,7 @@ Class UnrealHUD : BaseStatusBar
}
}
private void DrawArmor( double x, double y, bool bDrawOne )
private void DrawArmor( double x, double y, bool bDrawOne = false )
{
int ArmorAmount = 0, CurAbs = 0;
Inventory Inv, BestArmor;
@ -332,16 +355,12 @@ Class UnrealHUD : BaseStatusBar
{
CurX = x;
CurY = y;
if ( !CPlayer.ReadyWeapon || !CPlayer.ReadyWeapon.Ammo1 )
{
Screen.DrawTexture(IconBase,false,CurX,CurY,DTA_VirtualWidthF,ClipX,DTA_VirtualHeightF,ClipY,DTA_KeepRatio,true);
return;
}
if ( !CPlayer.ReadyWeapon || !CPlayer.ReadyWeapon.Ammo1 ) return;
Font cfont = LargeFont;
if ( CPlayer.ReadyWeapon.Ammo1.Amount < 10 ) cfont = LargeRedFont;
if ( CPlayer.ReadyWeapon.Ammo1.Amount <= min(9,CPlayer.ReadyWeapon.Ammo1.MaxAmount/3) ) cfont = LargeRedFont;
if ( !HudMode )
{
CurX -= cfont.StringWidth(String.Format("%d",CPlayer.ReadyWeapon.Ammo1.Amount));
CurX -= cfont.StringWidth(String.Format("%d",CPlayer.ReadyWeapon.Ammo1.Amount))+2;
Screen.DrawText(cfont,Font.CR_UNTRANSLATED,CurX,CurY,String.Format("%d",CPlayer.ReadyWeapon.Ammo1.Amount),DTA_VirtualWidthF,ClipX,DTA_VirtualHeightF,ClipY,DTA_KeepRatio,true);
}
CurX = x;
@ -360,6 +379,7 @@ Class UnrealHUD : BaseStatusBar
CurY = Y+29;
if ( (HudMode != 1) && (HudMode != 2) && (HudMode != 4) )
Screen.DrawTexture(HudLine,false,CurX,CurY,DTA_VirtualWidthF,ClipX,DTA_VirtualHeightF,ClipY,DTA_KeepRatio,true,DTA_WindowRightF,Min(27.*(CPlayer.ReadyWeapon.Ammo1.Amount/double(CPlayer.ReadyWeapon.Ammo1.MaxAmount)),27.));
// TODO secondary ammo display
}
private void DrawHealth( double x, double y )
@ -411,13 +431,13 @@ Class UnrealHUD : BaseStatusBar
{
if ( HudMode == 5 )
{
DrawInventory(ClipX-96,0,false);
DrawInventory(ClipX-96,0);
return;
}
if ( ClipX < 320 ) HudMode = 4;
// Draw Armor
if ( HudMode < 2 ) DrawArmor(0,0,false);
else if ( (HudMode == 3) || (HudMode == 2) ) DrawArmor(0,ClipY-32,false);
if ( HudMode < 2 ) DrawArmor(0,0);
else if ( (HudMode == 3) || (HudMode == 2) ) DrawArmor(0,ClipY-32);
else if ( HudMode == 4 ) DrawArmor(ClipX-64,ClipY-64,true);
// Draw Ammo
if ( HudMode != 4 ) DrawAmmo(ClipX-96,ClipY-32);
@ -427,10 +447,10 @@ Class UnrealHUD : BaseStatusBar
else if ( (HudMode == 3) || (HudMode == 2) ) DrawHealth(ClipX-128,ClipY-32);
else if ( HudMode == 4 ) DrawHealth(ClipX-64,ClipY-32);
// Display Inventory
if ( HudMode < 2 ) DrawInventory(ClipX-96,0,false);
else if ( HudMode == 3 ) DrawInventory(ClipX-96,ClipY-64,false);
if ( HudMode < 2 ) DrawInventory(ClipX-96,0);
else if ( HudMode == 3 ) DrawInventory(ClipX-96,ClipY-64);
else if ( HudMode == 4 ) DrawInventory(ClipX-64,ClipY-64,true);
else if ( HudMode == 2 ) DrawInventory(ClipX/2-64,ClipY-32,false);
else if ( HudMode == 2 ) DrawInventory(ClipX/2-64,ClipY-32);
// Display Frag count
if ( HudMode < 3 ) DrawFragCount(ClipX-32,ClipY-64);
else if ( HudMode == 3 ) DrawFragCount(0,ClipY-64);
@ -442,6 +462,51 @@ Class UnrealHUD : BaseStatusBar
DrawIdentifyInfo();
}
private void DrawUnrealBar()
{
// 0.83 status bar, just for funsies
DrawImage("Bar083",(0,336),DI_ITEM_OFFSETS);
static const float slotofs[] = {525, 84, 128, 173, 216, 259, 349, 392, 436, 481};
for ( int i=0; i<10; i++ )
{
if ( !CPlayer.HasWeaponsInSlot(i) ) continue;
bool used = (CPlayer.ReadyWeapon&&(CPlayer.ReadyWeapon.SlotNumber==i));
DrawImage("Slot083",(slotofs[i],342),DI_ITEM_OFFSETS,used?1.:.8);
}
DrawString(mOldDigits,FormatNumber(CPlayer.health,3),(359,367),DI_TEXT_ALIGN_RIGHT);
int ArmorAmount = 0, CurAbs = 0;
Inventory BestArmor = null;
for ( Inventory Inv=CPlayer.mo.Inv; Inv; Inv=Inv.Inv )
{
if ( !(Inv is 'UTArmor') ) continue;
ArmorAmount += Inv.Amount;
if ( Inv.Amount <= 0 ) continue;
if ( UTArmor(Inv).absorb > CurAbs )
{
CurAbs = UTArmor(Inv).absorb;
BestArmor = Inv;
}
}
// TODO draw different icons based on armor class
if ( BestArmor ) DrawImage("Armor083",(4,340),DI_ITEM_OFFSETS);
if ( ArmorAmount ) DrawString(mOldDigits,FormatNumber(ArmorAmount,3),(168,367),DI_TEXT_ALIGN_RIGHT);
Inventory Ammo1, Ammo2;
[Ammo1, Ammo2] = GetCurrentAmmo();
if ( Ammo1 )
{
if ( Ammo1.Amount ) DrawString(mOldDigits,FormatNumber(Ammo1.Amount,3),(550,367),DI_TEXT_ALIGN_RIGHT);
for ( int i=0; i<32; i++ )
{
if ( !(Ammo1 is OldAmmoType[i]) ) continue;
DrawImage(OldAmmo[i],(560,336),DI_ITEM_OFFSETS);
break;
}
}
// Need to draw the inventory bar (and translator)
if ( ClipX < 320 ) HudMode = 4;
DrawInventory(ClipX-96,0,false,true);
}
override void Tick()
{
Super.Tick();

View file

@ -101,3 +101,35 @@ Class OptionMenuItemHudType : OptionMenuItem
return -1;
}
}
// because I can't change the font color in mapinfo
Class GreenMessageBox : MessageBoxMenu
{
override void Drawer ()
{
int i, y;
int fontheight = textFont.GetHeight();
y = destHeight/2;
int c = mMessage.Count();
y -= c*fontHeight/2;
for ( i=0; i<c; i++ )
{
screen.DrawText (textFont,Font.CR_GREEN,(destWidth/2)-mMessage.StringWidth(i)/2,y,mMessage.StringAt(i),DTA_VirtualWidth,destWidth,DTA_VirtualHeight,destHeight,DTA_KeepRatio,true);
y += fontheight;
}
if ( mMessageMode == 0 )
{
y += fontheight;
mMouseY = y;
screen.DrawText(textFont,(messageSelection==0)?Font.CR_WHITE:Font.CR_DARKGREEN,destWidth/2,y,Stringtable.Localize("$TXT_YES"),DTA_VirtualWidth,destWidth,DTA_VirtualHeight,destHeight,DTA_KeepRatio,true);
screen.DrawText(textFont,(messageSelection==1)?Font.CR_WHITE:Font.CR_DARKGREEN,destWidth/2,y+fontheight,Stringtable.Localize("$TXT_NO"),DTA_VirtualWidth,destWidth,DTA_VirtualHeight,destHeight,DTA_KeepRatio,true);
if ( messageSelection >= 0 )
{
if ( (MenuTime()%8) < 6 )
{
screen.DrawText(arrowFont,OptionMenuSettings.mFontColorSelection,(destWidth/2)-11,y+fontheight*messageSelection,selector,DTA_VirtualWidth,destWidth,DTA_VirtualHeight,destHeight,DTA_KeepRatio,true);
}
}
}
}
}