Implemented "Item Sense" feature.

Rebalanced Hellblazer.
Rebalanced Biospark Carbine combo.
Hellblazer Crackshot sub-grenades home in on bounce, as was intended.
Added zoom blur when dashing.
Added option to use a big font for targetter labels.
More robust ui<->play communication for Demolitionist menu actions.
Increase fuel regen rate.
Disable GZDoom's built-in back button on Demolitionist Menu, since in some cases it can render the top left of the menu inaccessible.
This commit is contained in:
Mari the Deer 2020-08-16 16:21:08 +02:00
commit 09cfb25c30
16 changed files with 512 additions and 124 deletions

View file

@ -1,9 +1,8 @@
Fundamental things before beta:
- Ynykron Artifact altfire
Not so fundamental things during beta:
Not so fundamental things during first beta:
- Extra Demolitionist animations (swimming, additional gestures)
- Item detection button (highlights nearby, visible items)
- Dual wielding Explodium Gun
- Quick grenade function (Explodium Mag)
- Allow loading partial mags from spare bullets
@ -14,6 +13,7 @@ Not so fundamental things during beta:
- Confetti gibs
- Keen replacement (need ideas)
- Achievements
- Extra Demolitionist Menu tabs (radio, pong minigame)
- Collectables
Extra things for later:
@ -24,7 +24,6 @@ Extra things for later:
- A background with a bit more flair than just the fuzz shader
- Some sort of flyby featuring the Demolitionist booting up, closeups of weapons/items etc.
- Japanese localization
- Extra Demolitionist Menu tabs (radio, pong minigame)
- Mod trailer video
- Rewrite the entire Demolitionist Menu code from the ground up to be more easily extensible and adapt to any window size

View file

@ -53,6 +53,7 @@ user int swwm_barscale = 0; // target healthbar scaling (0 = use GZDoom scalin
user int swwm_scrscale = 0; // score scaling (0 = use GZDoom scaling)
user int swwm_numscale = 0; // damnum scaling (0 = use GZDoom scaling)
user int swwm_poiscale = 0; // point of interest scaling (0 = use GZDoom scaling)
user int swwm_detscale = 0; // item sense scaling (0 = use GZDoom scaling)
server bool swwm_blood = false; // custom blood/gibbing
user bool swwm_fuzz = true; // allows toggling the fuzz shader on the demolitionist menus, useful if you're streaming/recording since it destroys the encoding quality
user bool swwm_cbtpause = true; // wallbuster menu pauses the game
@ -73,3 +74,4 @@ user bool swwm_funtags = true; // replace vanilla monster names with silly one
//server bool swwm_superfuel = false; // TODO enable unlimited fuel
//server bool swwm_partytime = false; // TODO killed enemies burst into confetti
server bool swwm_simplefog = false; // simplified teleport fogs (useful to speed up slaughterwads)
user bool swwm_bigtags = false; // use a bigger font for targeter tags

View file

@ -1,4 +1,12 @@
HardwareShader PostProcess beforebloom
{
Name "ZoomBlur"
Shader "shaders/glsl/ZoomBlur.fp" 330
Uniform float Str
Uniform float Fade
Uniform vec2 CenterSpot
}
HardwareShader PostProcess beforebloom
{
Name "SilverScope"
Shader "shaders/glsl/SilverScope.fp" 330

View file

@ -3,11 +3,14 @@ addmenukey "$SWWM_PRIMARYFIRE" "+attack"
addmenukey "$SWWM_SECONDARYFIRE" "+altattack"
addmenukey "$SWWM_RELOADFIRE" "+reload"
addmenukey "$SWWM_ZOOMFIRE" "+zoom"
//addmenukey "$SWWM_EXTRAFIRE" "+user4"
addmenukey "$SWWM_MELEE" "+user1"
addmenukey "$SWWM_DASH" "+user2"
addmenukey "$SWWM_ITEMSENSE" "+user3"
addmenukey "$SWWM_GESTURE1" "netevent swwmgesture 0"
addmenukey "$SWWM_GESTURE2" "netevent swwmgesture 1"
addmenukey "$SWWM_GESTURE3" "netevent swwmgesture 2"
//addmenukey "$SWWM_GESTURE4" "netevent swwmgesture 3"
addmenukey "$SWWM_KBASE" "openmenu SWWMKnowledgeBaseMenu"
defaultbind "j" "netevent swwmgesture 0"
defaultbind "k" "netevent swwmgesture 1"

View file

@ -7,9 +7,12 @@ SWWM_RELOADFIRE = "Reload";
SWWM_ZOOMFIRE = "Tertiary Fire / Zoom";
SWWM_MELEE = "Melee Attack";
SWWM_DASH = "Dash";
SWWM_ITEMSENSE = "Item Sense";
SWWM_EXTRAFIRE = "Quaternary Fire";
SWWM_GESTURE1 = "Wave";
SWWM_GESTURE2 = "Thumbs Up";
SWWM_GESTURE3 = "Victory";
SWWM_GESTURE4 = "Blow Kiss";
SWWM_KBASE = "Demolitionist Menu";
// mod menu
SWWM_MTITLE = "SWWM GZ Options";
@ -96,6 +99,7 @@ SWWM_BARSCALE = "Healthbar Scaling";
SWWM_NUMSCALE = "Number Scaling";
SWWM_SCRSCALE = "Score Scaling";
SWWM_POISCALE = "POI Scaling";
SWWM_DETSCALE = "Item Sense Scaling";
SWWM_GZSCALE = "Use GZDoom Setting";
SWWM_BLOOD = "Enable Custom Blood";
SWWM_FUZZ = "Enable Animated Menu BG";
@ -111,6 +115,7 @@ SWWM_MENUPAUSE = "Pause on Demolitionist Menu";
SWWM_FTITLE = "Fun Options";
SWWM_FUNTAGS = "Monster Renaming";
SWWM_SIMPLEFOG = "Simplified Teleport Fog";
SWWM_BIGTAGS = "Use Large Font for Names";
TOOLTIP_SWWM_VOICETYPE = "Sets the voice pack for the player.";
TOOLTIP_SWWM_MUTEVOICE = "Control what gets muted, if you'd rather have a more silent protagonist.";
TOOLTIP_SWWM_FLASHSTRENGTH = "Screen flashes usually happen when firing some weapons, you can lower this if these effects are harmful for you.";
@ -154,6 +159,7 @@ TOOLTIP_SWWM_BARSCALE = "Scaling factor for targetter healthbars. Set to 0 to us
TOOLTIP_SWWM_NUMSCALE = "Scaling factor for damage/healing numbers. Set to 0 to use GZDoom's own HUD scaling.";
TOOLTIP_SWWM_SCRSCALE = "Scaling factor for score numbers. Set to 0 to use GZDoom's own HUD scaling.";
TOOLTIP_SWWM_POISCALE = "Scaling factor for points of interest. Set to 0 to use GZDoom's own HUD scaling.";
TOOLTIP_SWWM_DETSCALE = "Scaling factor for sensed items. Set to 0 to use GZDoom's own HUD scaling.";
TOOLTIP_SWWM_BLOOD = "Please note that these effects are kinda cheap and performance heavy. I'd honestly recommend Nashgore instead, it's better.";
TOOLTIP_SWWM_FUZZ = "Toggling this off is recommended if you're recording/streaming as this effect can harm video quality.";
TOOLTIP_SWWM_CBTPAUSE = "The game will pause while the Wallbuster reload menu is open (only in singleplayer).";
@ -167,6 +173,7 @@ TOOLTIP_SWWM_YNYKRONALERT = "By default the Ynykron wakes all monsters in the ma
TOOLTIP_SWWM_MENUPAUSE = "In single player, the Demolitionist Menu by default will pause everything. You can disable this if you want a more Souls-like experience (or if you want to have a read while actively waiting for some looooooooong elevator or other timed event).";
TOOLTIP_SWWM_FUNTAGS = "Replaces the names of various vanilla monsters with funny alternatives.";
TOOLTIP_SWWM_SIMPLEFOG = "Replaces particle-based teleport fogs with simple sprites. Useful if they cause performance issues.";
TOOLTIP_SWWM_BIGTAGS = "By default name labels on healthbars are shown with a small, compact font. Enabling this will use a bigger one.";
// knowledge base
SWWM_COMINGSOON = "(coming soon)";
SWWM_MISSTAB = "Mission";

View file

@ -7,9 +7,12 @@ SWWM_RELOADFIRE = "Recargar";
SWWM_ZOOMFIRE = "Fuego Terciario / Zoom";
SWWM_MELEE = "Ataque a Melé";
SWWM_DASH = "Esprintar";
SWWM_ITEMSENSE = "Sensor de Items";
SWWM_EXTRAFIRE = "Fuego Cuaternario";
SWWM_GESTURE1 = "Saludar";
SWWM_GESTURE2 = "Pulgar Arriba";
SWWM_GESTURE3 = "Victoria";
SWWM_GESTURE4 = "Soplar Beso";
SWWM_KBASE = "Menú de Demolicionista";
// mod menu
SWWM_MTITLE = "Opciones de SWWM GZ";
@ -93,6 +96,7 @@ SWWM_BARSCALE = "Escala de Barras de Salud";
SWWM_NUMSCALE = "Escala de Números";
SWWM_SCRSCALE = "Escala de Puntuaciones";
SWWM_POISCALE = "Escala de Puntos de Interés";
SWWM_DETSCALE = "Escala de Sensor de Items";
SWWM_GZSCALE = "Usar Opción de GZDoom";
SWWM_BLOOD = "Habilitar Sangre Personalizada";
SWWM_FUZZ = "Habilitar Fondo Animado de Menú";
@ -108,6 +112,7 @@ SWWM_MENUPAUSE = "Pausar en Menú de Demolicionista";
SWWM_FTITLE = "Opciones Divertidas";
SWWM_FUNTAGS = "Renombrar Monstruos";
SWWM_SIMPLEFOG = "Efecto de Teletransporte Simple"
SWWM_BIGTAGS = "Usar Fuente Grande para Nombres";
TOOLTIP_SWWM_VOICETYPE = "Selecciona el pack de voz para el jugador.";
TOOLTIP_SWWM_MUTEVOICE = "Controla lo que se mutea, si prefieres tener un protagonista más silencioso.";
TOOLTIP_SWWM_FLASHSTRENGTH = "Los destellos en pantalla suelen ocurrir al disparar algunas armas, puedes reducirlo si este tipo de effectos te causan malestar.";
@ -151,6 +156,7 @@ TOOLTIP_SWWM_BARSCALE = "Factor de escalado para las barras de salud. Pon a 0 pa
TOOLTIP_SWWM_NUMSCALE = "Factor de escalado para los números de daño/salud. Pon a 0 para usar el escalado de HUD de GZDoom.";
TOOLTIP_SWWM_SCRSCALE = "Factor de escalado para los números de puntuación. Pon a 0 para usar el escalado de HUD de GZDoom.";
TOOLTIP_SWWM_POISCALE = "Factor de escalado para los puntos de interés. Pon a 0 para usar el escalado de HUD de GZDoom.";
TOOLTIP_SWWM_DETSCALE = "Factor de escalado para los items detectados. Pon a 0 para usar el escalado de HUD de GZDoom.";
TOOLTIP_SWWM_BLOOD = "Ten en cuenta que estos efectos son un poco cutres y bajan los frames. Sinceramente, recomendaría usar Nashgore, es mejor.";
TOOLTIP_SWWM_FUZZ = "Desactivar ésto es recomendado si estás grabando o haciendo streaming, ya que este effecto puede dañar la calidad del vídeo.";
TOOLTIP_SWWM_CBTPAUSE = "El juego será pausado mientras el menú de recarga de Wallbuster está abierto (sólo en modo de un jugador).";
@ -164,6 +170,7 @@ TOOLTIP_SWWM_YNYKRONALERT = "Por defecto el Ynykron alerta a todos los monstruos
TOOLTIP_SWWM_MENUPAUSE = "En modo de un jugador, el Menú de Demolicionista por defecto paus a todo. Puedes desactivar esto si quieres una experiencia más Souls-like (o si quieres leer un poco mientras esperas activamente algun ascensor leeeeeeento o algún otro evento temporizado)."
TOOLTIP_SWWM_FUNTAGS = "Reemplaza los nombres de monstruos vanilla por alternativas graciosas.";
TOOLTIP_SWWM_SIMPLEFOG = "Reemplaza los efectos de teletransporte basados en partículas con simples sprites. Útil si causan problemas de rendimiento.";
TOOLTIP_SWWM_BIGTAGS = "Por defecto los nombres de las barras de vida usan una fuente pequeña. Activando esta opción, se cambiará por una mayor.";
// knowledge base
SWWM_COMINGSOON = "(próximamente)";
SWWM_MISSTAB = "Misión";

View file

@ -1,2 +1,2 @@
[default]
SWWM_MODVER="\chSWWM \cwGZ\c- r484 (Sun 16 Aug 01:24:54 CEST 2020)";
SWWM_MODVER="\chSWWM \cwGZ\c- r486 (Sun 16 Aug 16:27:44 CEST 2020)";

View file

@ -44,6 +44,7 @@ OptionMenu "SWWMOptionMenu"
Slider "$SWWM_PICKLEN", "swwm_pickduration", 1, 30, 1, 0
Option "$SWWM_TARGET", "swwm_targeter", "YesNo"
Option "$SWWM_TARGETTAG", "swwm_targettags", "YesNo"
Option "$SWWM_BIGTAGS", "swwm_bigtags", "YesNo"
Option "$SWWM_BOSSBAR", "swwm_bosshealthbars", "YesNo"
Option "$SWWM_DAMNUMS", "swwm_healthnums", "YesNo"
Option "$SWWM_ACCDAMAGE", "swwm_accdamage", "YesNo"
@ -58,6 +59,7 @@ OptionMenu "SWWMOptionMenu"
ScaleSlider "$SWWM_NUMSCALE", "swwm_numscale", 0, 8, 1, "$SWWM_GZSCALE"
ScaleSlider "$SWWM_SCRSCALE", "swwm_scrscale", 0, 8, 1, "$SWWM_GZSCALE"
ScaleSlider "$SWWM_POISCALE", "swwm_poiscale", 0, 8, 1, "$SWWM_GZSCALE"
ScaleSlider "$SWWM_DETSCALE", "swwm_detscale", 0, 8, 1, "$SWWM_GZSCALE"
Option "$SWWM_SHADERS", "swwm_shaders", "YesNo"
Option "$SWWM_INTERTYPE", "swwm_intertype", "SWWMInterType"
Option "$SWWM_FUZZ", "swwm_fuzz", "YesNo"

18
shaders/glsl/ZoomBlur.fp Normal file
View file

@ -0,0 +1,18 @@
void main()
{
vec2 p = CenterSpot-TexCoord;
vec4 res = vec4(0.);
vec2 d = (p/150.)*Str;
float w = 1.;
vec2 s = TexCoord;
float sum = 0.;
for ( int i=0; i<16; i++ )
{
res += w*texture(InputTexture,s);
sum += w;
w *= .8;
s += d;
}
res /= sum;
FragColor = mix(texture(InputTexture,TexCoord),vec4(res.rgb,1.),Fade);
}

View file

@ -251,7 +251,7 @@ Class HellblazerMissile : Actor
A_SetRenderStyle(1.0,STYLE_Add);
A_SprayDecal("BigScorch",50);
A_SetScale(4.5);
SWWMHandler.DoExplosion(self,500,320000,200,90);
SWWMHandler.DoExplosion(self,250,320000,200,90);
A_NoGravity();
A_QuakeEx(5,5,5,15,0,1500,"",QF_RELATIVE|QF_SCALEDOWN,falloff:500,rollIntensity:.8);
A_StopSound(CHAN_BODY);
@ -347,7 +347,7 @@ Class HellblazerCrackshot : HellblazerMissile
A_SetRenderStyle(1.0,STYLE_Add);
A_SprayDecal("BigScorch",50);
A_SetScale(6.);
SWWMHandler.DoExplosion(self,500,320000,250,100);
SWWMHandler.DoExplosion(self,300,320000,250,100);
A_NoGravity();
A_QuakeEx(6,6,6,20,0,2000,"",QF_RELATIVE|QF_SCALEDOWN,falloff:800,rollIntensity:1.);
A_StopSound(CHAN_BODY);
@ -416,7 +416,7 @@ Class HellblazerRavager : HellblazerMissile
A_SetRenderStyle(1.0,STYLE_Add);
A_SprayDecal("HugeScorch",50);
A_SetScale(8.);
SWWMHandler.DoExplosion(self,800,320000,300,120);
SWWMHandler.DoExplosion(self,500,320000,300,120);
A_NoGravity();
A_QuakeEx(6,6,6,30,0,2000,"",QF_RELATIVE|QF_SCALEDOWN,falloff:800,rollIntensity:1.);
A_StopSound(CHAN_BODY);
@ -494,7 +494,7 @@ Class HellblazerWarhead : HellblazerMissile
A_SetRenderStyle(1.0,STYLE_Add);
A_SprayDecal("WumboScorch",150);
A_SetScale(7.);
SWWMHandler.DoExplosion(self,3000,600000,400,200);
SWWMHandler.DoExplosion(self,2000,600000,400,200);
A_NoGravity();
A_QuakeEx(9,9,9,150,0,12000,"",QF_RELATIVE|QF_SCALEDOWN,falloff:4000,rollIntensity:2.);
A_StopSound(CHAN_BODY);
@ -647,7 +647,7 @@ Mixin Class HellblazerGrenade
ReactionTime--;
if ( ReactionTime <= 0 ) ExplodeMissile();
}
void A_HandleBounce()
virtual void A_HandleBounce()
{
Vector3 HitNormal = -vel.unit();
F3DFloor ff;
@ -759,7 +759,7 @@ Class HellblazerClusterMini : HellblazerMissile2
s.alpha *= .4;
s.vel = .3*vel + (traildir+(FRandom[Hellblazer](-.4,.4),FRandom[Hellblazer](-.4,.4),FRandom[Hellblazer](-.4,.4))).unit()*FRandom[Hellblazer](1.,2.);
}
if ( (deto > 1) && (special2 > 2) )
if ( (deto > 1) && (special2 > 5) )
{
ExplodeMissile();
return;
@ -769,7 +769,7 @@ Class HellblazerClusterMini : HellblazerMissile2
while ( bt.Next() )
{
let t = bt.Thing;
if ( !t || !t.bSHOOTABLE || (!t.bISMONSTER && !(t is 'BossBrain')) || (t.Health <= 0) || (target && t.IsFriend(target)) || !SWWMUtility.SphereIntersect(t,level.Vec3Offset(pos,vel),80) || !CheckSight(t,SF_IGNOREVISIBILITY|SF_IGNOREWATERBOUNDARY) ) continue;
if ( !t || !t.bSHOOTABLE || (!t.bISMONSTER && !(t is 'BossBrain')) || (t.Health <= 0) || (target && t.IsFriend(target)) || !SWWMUtility.SphereIntersect(t,level.Vec3Offset(pos,vel),60) || !CheckSight(t,SF_IGNOREVISIBILITY|SF_IGNOREWATERBOUNDARY) ) continue;
deto++;
break;
}
@ -782,7 +782,7 @@ Class HellblazerClusterMini : HellblazerMissile2
A_SetRenderStyle(1.0,STYLE_Add);
A_SprayDecal("BigScorch",50);
A_SetScale(2.5);
SWWMHandler.DoExplosion(self,100,200000,150,60);
SWWMHandler.DoExplosion(self,80,200000,150,60);
A_NoGravity();
A_QuakeEx(4,4,4,12,0,1000,"",QF_RELATIVE|QF_SCALEDOWN,falloff:400,rollIntensity:.6);
A_StopSound(CHAN_BODY);
@ -856,6 +856,31 @@ Class HellblazerClusterMini : HellblazerMissile2
p.alpha *= 1-special1*.1;
}
}
override void A_HandleBounce()
{
Super.A_HandleBounce();
if ( !bMISSILE ) return;
// try to steer towards a target
let bt = BlockThingsIterator.Create(self,800);
double closest = double.infinity;
Actor whomst = null;
while ( bt.Next() )
{
let t = bt.Thing;
if ( !t || !t.bSHOOTABLE || (!t.bISMONSTER && !(t is 'BossBrain')) || (t.Health <= 0) || (target && t.IsFriend(target)) || !SWWMUtility.SphereIntersect(t,level.Vec3Offset(pos,vel),800) || !CheckSight(t,SF_IGNOREVISIBILITY|SF_IGNOREWATERBOUNDARY) ) continue;
double dist = Distance3D(t);
if ( dist > closest ) continue;
closest = dist;
whomst = t;
}
if ( !whomst ) return;
Vector3 dirto = level.Vec3Diff(pos,whomst.Vec3Offset(0,0,whomst.Height/2));
dirto /= dirto.length();
dirto.z += .3;
double spd = vel.length();
vel /= spd;
vel = (vel*.3+dirto*.7)*spd;
}
States
{

View file

@ -1285,6 +1285,77 @@ Class SWWMInterest : Thinker
}
}
Class SWWMItemSense : Thinker
{
Inventory item;
String tag;
int updated;
Demolitionist parent;
SWWMItemSense prev, next;
Vector3 pos;
static SWWMItemSense Spawn( Demolitionist parent, Inventory item )
{
if ( !parent || !item ) return null;
// only refresh the updated time if existing
for ( SWWMItemSense s=parent.itemsense; s; s=s.next )
{
if ( s.item != item ) continue;
s.updated = level.maptime+35;
s.pos = item.Vec3Offset(0,0,16);
return s;
}
let i = new("SWWMItemSense");
i.ChangeStatNum(STAT_USER);
i.item = item;
i.parent = parent;
i.updated = level.maptime+35;
i.UpdateTag();
i.pos = item.Vec3Offset(0,0,16);
i.next = parent.itemsense;
if ( parent.itemsense ) parent.itemsense.prev = i;
parent.itemsense = i;
parent.itemsense_cnt++;
return i;
}
void UpdateTag()
{
if ( !item ) return;
tag = item.GetTag();
}
override void OnDestroy()
{
if ( parent )
{
parent.itemsense_cnt--;
if ( !prev )
{
parent.itemsense = next;
if ( next ) next.prev = null;
}
else
{
prev.next = next;
if ( next ) next.prev = prev;
}
}
Super.OnDestroy();
}
override void Tick()
{
if ( !parent )
{
Destroy();
return;
}
// expire
if ( level.maptime > updated+70 ) Destroy();
}
}
// enemy combat tracker
Class SWWMCombatTracker : Thinker
{
@ -2527,6 +2598,9 @@ Class SWWMHandler : EventHandler
// heal/armor flashes need to be handled here so they don't stack
transient int hflash[MAXPLAYERS], aflash[MAXPLAYERS];
// for menu events
transient Array<MenuTransaction> checklist;
transient CVar mutevoice, accdamage;
transient ui CVar useshaders;
transient CVar lang;
@ -2775,6 +2849,13 @@ Class SWWMHandler : EventHandler
SWWMStats s;
while ( s = SWWMStats(ti.Next()) )
s.AddLevelStats();
PlayerInfo p = players[consoleplayer];
Shader.SetEnabled(p,"ZoomBlur",false);
Shader.SetEnabled(p,"RagekitShader",false);
Shader.SetEnabled(p,"GhostShader",false);
Shader.SetEnabled(p,"InvinciShader",false);
Shader.SetEnabled(p,"Glitch",false);
Shader.SetEnabled(p,"Grain",false);
}
override void WorldLoaded( WorldEvent e )
@ -2865,6 +2946,7 @@ Class SWWMHandler : EventHandler
}
}
PlayerInfo p = players[consoleplayer];
Shader.SetEnabled(p,"ZoomBlur",false);
Shader.SetEnabled(p,"RagekitShader",false);
Shader.SetEnabled(p,"GhostShader",false);
Shader.SetEnabled(p,"InvinciShader",false);
@ -3778,6 +3860,7 @@ Class SWWMHandler : EventHandler
if ( amt > maxgive ) amt = maxgive;
}
else if ( amt > def.MaxAmount ) amt = def.MaxAmount;
bool rslt = false;
if ( (amt > 0) && players[e.Args[1]].mo.GiveInventory(item,amt,true) )
{
players[e.Args[0]].mo.TakeInventory(item,amt);
@ -3787,6 +3870,17 @@ Class SWWMHandler : EventHandler
// add messages
if ( e.Args[0] == consoleplayer ) Console.Printf(StringTable.Localize("$SWWM_MSGSENT"),amt,def.GetTag(),players[e.Args[1]].GetUserName());
if ( e.Args[1] == consoleplayer ) Console.Printf(StringTable.Localize("$SWWM_MSGRECV"),players[e.Args[0]].GetUserName(),amt,def.GetTag());
rslt = true;
}
if ( e.Args[0] == consoleplayer )
{
let t = new("MenuTransaction");
t.uid = e.Args[2];
t.type = MenuTransaction.TT_ITEMSEND;
t.result = rslt;
t.used = item;
t.usedup = (players[e.Args[1]].mo.CountInv(item)<=0);
checklist.Push(t);
}
}
else if ( e.Name.Left(17) ~== "swwmmarkloreread." )
@ -3801,7 +3895,19 @@ Class SWWMHandler : EventHandler
if ( !item ) return;
let i = players[e.Args[0]].mo.FindInventory(item);
if ( !i ) return;
players[e.Args[0]].mo.UseInventory(i);
bool rslt = players[e.Args[0]].mo.UseInventory(i);
if ( e.Args[0] == consoleplayer )
{
let t = new("MenuTransaction");
t.uid = e.Args[1];
t.type = MenuTransaction.TT_ITEMUSE;
let w = (Class<Weapon>)(item);
if ( w ) t.result = (players[e.Args[0]].PendingWeapon==Weapon(i));
else t.result = rslt;
t.used = item;
t.usedup = (!i||(i.Amount<=0));
checklist.Push(t);
}
}
else if ( e.Name.Left(13) ~== "swwmdropitem." )
{
@ -3824,6 +3930,16 @@ Class SWWMHandler : EventHandler
let drop = players[e.Args[0]].mo.DropInventory(i,amt);
// add some random velocity so multiple drops don't get bunched together
if ( drop ) drop.vel += (Actor.RotateVector((FRandom[Junk](-1.5,.5),FRandom[Junk](-2.5,2.5)),players[e.Args[0]].mo.angle),FRandom[Junk](2.,5.));
if ( e.Args[0] == consoleplayer )
{
let t = new("MenuTransaction");
t.uid = e.Args[1];
t.type = MenuTransaction.TT_ITEMDROP;
t.used = item;
t.result = drop;
t.usedup = (!i||(i.Amount<=0));
checklist.Push(t);
}
}
else if ( e.Name ~== "swwmkoraxline" )
{
@ -3905,6 +4021,21 @@ Class SWWMHandler : EventHandler
}
cbt.waitreload = false;
}
else if ( e.Name ~== "swwmcleartransaction" )
{
if ( e.Args[1] != consoleplayer ) return;
for ( int i=0; i<checklist.Size(); i++ )
{
if ( checklist[i].uid != e.Args[0] ) continue;
checklist.Delete(i);
i--;
}
}
else if ( e.Name ~== "swwmclearalltransactions" )
{
if ( e.Args[0] != consoleplayer ) return;
checklist.Clear();
}
}
// stuff for hud
@ -3983,11 +4114,37 @@ Class SWWMHandler : EventHandler
Shader.SetUniform1f(p,"Glitch","str1",noiz);
noiz = min(lastdmg*.03*max(0,(lastdmgtic-(gametic+e.Fractic))/35.),3.5);
Shader.SetUniform1f(p,"Glitch","str2",noiz);
Shader.SetEnabled(p,"ZoomBlur",true);
if ( !demo.InStateSequence(demo.CurState,demo.FindState("Dash")) )
{
Shader.SetEnabled(p,"ZoomBlur",false);
return;
}
Vector3 vel = demo.vel+demo.dashdir*demo.dashboost;
double baumpu = max(0.,(demo.bumptic-(gametic+e.Fractic))/35.);
vel *= 1.+baumpu;
double spd = vel.length();
Vector3 worlddir = vel/spd;
Shader.SetUniform1f(p,"ZoomBlur","Fade",clamp((spd-20.)/60.,0.,.5));
double str = min(spd/50.,10.);
Vector3 x, y, z;
[x, y, z] = swwm_CoordUtil.GetAxes(e.ViewPitch,e.ViewAngle,e.ViewRoll);
Vector3 reldir = (worlddir dot y, worlddir dot z, worlddir dot x);
Vector2 centerspot = (.5+reldir.x*.5,.5+reldir.y*.5);
if ( reldir.z < 0 )
{
centerspot.x = 1.-centerspot.x;
centerspot.y = 1.-centerspot.y;
str *= -1;
}
Shader.SetUniform1f(p,"ZoomBlur","Str",str);
Shader.SetUniform2f(p,"ZoomBlur","CenterSpot",centerspot);
}
else
{
Shader.SetEnabled(p,"Glitch",false);
Shader.SetEnabled(p,"Grain",false);
Shader.SetEnabled(p,"ZoomBlur",false);
}
}

View file

@ -20,6 +20,7 @@ Class SWWMStatusBar : BaseStatusBar
Array<SWWMInterest> intpoints;
Array<SWWMScoreObj> scoreobjs;
Array<SWWMCombatTracker> trackers;
Array<SWWMItemSense> senseitems;
// the event handler, holding all sorts of stuff
SWWMHandler hnd;
@ -27,7 +28,7 @@ Class SWWMStatusBar : BaseStatusBar
SWWMVanillaBossHandler bosshnd;
// client cvars
transient CVar safezone, maxchat[2], maxpick, chatduration, msgduration, pickduration, chatcol, teamcol, obitcol, critcol, pickcol, targetter, healthnums, scorenums, scorebonus, pois, targettag, lang, maxtarg, maxscore, maxdamns, hscale, bscale, nscale, sscale, iscale, midcol, midbcol, midduration;
transient CVar safezone, maxchat[2], maxpick, chatduration, msgduration, pickduration, chatcol, teamcol, obitcol, critcol, pickcol, targetter, healthnums, scorenums, scorebonus, pois, targettag, lang, maxtarg, maxscore, maxdamns, hscale, bscale, nscale, sscale, iscale, dscale, midcol, midbcol, midduration, bigtags;
// shared stuff
Vector2 ss, hs;
@ -35,6 +36,7 @@ Class SWWMStatusBar : BaseStatusBar
Vector2 ssn, hsn;
Vector2 sss, hss;
Vector2 ssi, hsi;
Vector2 ssd, hsd;
int margin;
double FracTic;
int chatopen;
@ -350,6 +352,34 @@ Class SWWMStatusBar : BaseStatusBar
qsort_scoreobjs(a,p+1,h);
}
// quicksort (item sense)
private int partition_itemsense( Array<SWWMItemSense> a, int l, int h )
{
SWWMItemSense pv = a[h];
int i = (l-1);
for ( int j=l; j<=(h-1); j++ )
{
if ( CmpDist(pv.pos,a[j].pos) )
{
i++;
SWWMItemSense tmp = a[j];
a[j] = a[i];
a[i] = tmp;
}
}
SWWMItemSense tmp = a[h];
a[h] = a[i+1];
a[i+1] = tmp;
return i+1;
}
private void qsort_itemsense( Array<SWWMItemSense> a, int l, int h )
{
if ( l >= h ) return;
int p = partition_itemsense(a,l,h);
qsort_itemsense(a,l,p-1);
qsort_itemsense(a,p+1,h);
}
override void Tick()
{
Super.Tick();
@ -507,6 +537,31 @@ Class SWWMStatusBar : BaseStatusBar
scoreobjs.Resize(i);
// sort by distance
qsort_scoreobjs(scoreobjs,0,scoreobjs.Size()-1);
// check if player has item sense
let demo = Demolitionist(CPlayer.mo);
if ( demo && (demo.itemsense_cnt > 0) )
{
if ( senseitems.Size() != demo.itemsense_cnt )
senseitems.Resize(demo.itemsense_cnt);
total_sz = demo.itemsense_cnt;
i = 0;
for ( SWWMItemSense s=demo.itemsense; s && (i<total_sz); s=s.next )
{
// ignore points clearly outside of player view
Vector3 tdir = level.Vec3Diff(viewpos,s.pos);
if ( viewvec dot tdir < 0 ) continue;
proj.ProjectWorldPos(viewpos+tdir);
proj.ProjectToNormal();
if ( !proj.IsInFront() || !proj.IsInScreen() ) continue;
if ( !thesight && (level.maptime > s.updated+35) ) continue;
senseitems[i++] = s;
}
// squeeze if some were discarded
if ( i != total_sz )
senseitems.Resize(i);
// sort by distance
qsort_itemsense(senseitems,0,senseitems.Size()-1);
}
// part of gross hackery to override nametag display
if ( !ntags ) ntags = CVar.GetCVar('displaynametags',players[consoleplayer]);
if ( CPlayer.inventorytics > 0 )
@ -629,6 +684,29 @@ Class SWWMStatusBar : BaseStatusBar
Screen.DrawText(fnt,Font.CR_WHITE,(vpos.x-hsi.x*fnt.StringWidth(tag)/2.)/hsi.x,(vpos.y+hsi.y*fnt.GetHeight()/2.)/hsi.y,tag,DTA_VirtualWidthF,ssi.x,DTA_VirtualHeightF,ssi.y,DTA_KeepRatio,true);
}
}
// sensed items
let demo = Demolitionist(CPlayer.mo);
if ( demo && (demo.itemsense_cnt > 0) )
{
for ( int i=0; i<senseitems.Size(); i++ )
{
let s = senseitems[i];
if ( !s || !s.item ) continue;
Vector3 tdir = Level.Vec3Diff(ViewPos,s.pos);
proj.ProjectWorldPos(ViewPos+tdir);
Vector2 npos = proj.ProjectToNormal();
if ( !proj.IsInFront() ) continue;
Vector2 vpos = viewport.SceneToWindow(npos);
Font fnt = LangFont(mMiniwiFont);
int mtime = thesight?70:35;
double alph = clamp(((s.updated+mtime)-level.maptime)/35.,0.,1.);
alph *= clamp(1.5-1.5*(tdir.length()/(thesight?1200.:800.)),0.,1.);
tag = s.tag;
Screen.DrawText(fnt,Font.CR_GREEN,(vpos.x-hsd.x*fnt.StringWidth(tag)/2.)/hsd.x,(vpos.y-hsd.y*fnt.GetHeight()/2.)/hsd.y,tag,DTA_VirtualWidthF,ssd.x,DTA_VirtualHeightF,ssd.y,DTA_KeepRatio,true,DTA_Alpha,alph);
tag = String.Format("\cu(%s\cu)\c-",FormatDist(tdir.length()));
Screen.DrawText(fnt,Font.CR_WHITE,(vpos.x-hsd.x*fnt.StringWidth(tag)/2.)/hsd.x,(vpos.y+hsd.y*fnt.GetHeight()/2.)/hsd.y,tag,DTA_VirtualWidthF,ssd.x,DTA_VirtualHeightF,ssd.y,DTA_KeepRatio,true,DTA_Alpha,alph);
}
}
// targetting array
for ( int i=0; i<trackers.Size(); i++ )
{
@ -653,7 +731,8 @@ Class SWWMStatusBar : BaseStatusBar
barsiz.y *= hsb.y;
Vector2 barpos = vpos-(barsiz/2.);
barpos.y -= 16.;
Font fnt = LangFont(mMiniwiFont);
if ( !bigtags ) bigtags = CVar.GetCVar('swwm_bigtags',players[consoleplayer]);
Font fnt = LangFont(bigtags.GetBool()?mTewiFont:mMiniwiFont);
if ( targettag.GetBool() || targ.myplayer && (tag != "") )
Screen.DrawText(fnt,Font.CR_WHITE,(barpos.x+barsiz.x/2.-(fnt.StringWidth(tag)*hsb.x)/2.)/hsb.x,(barpos.y-fnt.GetHeight()*hsb.y)/hsb.y,tag,DTA_VirtualWidthF,ssb.x,DTA_VirtualHeightF,ssb.y,DTA_KeepRatio,true,DTA_Alpha,alph);
Screen.DrawTexture(EnemyBTex,false,barpos.x/hsb.x,barpos.y/hsb.y,DTA_VirtualWidthF,ssb.x,DTA_VirtualHeightF,ssb.y,DTA_KeepRatio,true,DTA_Alpha,alph);
@ -1295,6 +1374,7 @@ Class SWWMStatusBar : BaseStatusBar
if ( !nscale ) nscale = CVar.GetCVar('swwm_numscale',players[consoleplayer]);
if ( !sscale ) sscale = CVar.GetCVar('swwm_scrscale',players[consoleplayer]);
if ( !iscale ) iscale = CVar.GetCVar('swwm_poiscale',players[consoleplayer]);
if ( !dscale ) dscale = CVar.GetCVar('swwm_detscale',players[consoleplayer]);
BeginHUD();
if ( hscale.GetInt() <= 0 ) hs = GetHUDScale();
else
@ -1333,6 +1413,13 @@ Class SWWMStatusBar : BaseStatusBar
hsi.y = hsi.x;
}
ssi = (Screen.GetWidth()/hsi.x,Screen.GetHeight()/hsi.y);
if ( dscale.GetInt() <= 0 ) hsd = GetHUDScale();
else
{
hsd.x = dscale.GetInt();
hsd.y = hsd.x;
}
ssd = (Screen.GetWidth()/hsd.x,Screen.GetHeight()/hsd.y);
FracTic = TicFrac;
DrawTarget();
DrawScore();

View file

@ -1,4 +1,18 @@
// internal "knowledge base" and more
Class MenuTransaction
{
enum ETransactionType
{
TT_ITEMUSE,
TT_ITEMDROP,
TT_ITEMSEND
};
int uid, type;
Class<Inventory> used;
bool result, usedup;
}
Class SWWMKnowledgeBaseMenu : GenericMenu
{
enum EDemoTab
@ -61,11 +75,9 @@ Class SWWMKnowledgeBaseMenu : GenericMenu
// color for chat
CVar ccol, tcol;
// for checks (duh)
Class<Inventory> lastuse;
int lastuseamt;
int checkuse;
int checkdrop;
int checksend;
Array<MenuTransaction> checklist;
int lasttuid;
SWWMHandler hnd;
// seeeeecret
int kcode;
// crimey clock stuff
@ -82,6 +94,11 @@ Class SWWMKnowledgeBaseMenu : GenericMenu
return req;
}
int GenTUID()
{
return lasttuid++;
}
override void Init( Menu parent )
{
Super.Init(parent);
@ -89,6 +106,7 @@ Class SWWMKnowledgeBaseMenu : GenericMenu
{
// can't open this menu outside of the game or if dead
// also can't if you're not the Demolitionist
EventHandler.SendNetworkEvent("swwmclearalltransactions",consoleplayer);
Close();
return;
}
@ -119,6 +137,8 @@ Class SWWMKnowledgeBaseMenu : GenericMenu
stats = SWWMStats.Find(players[consoleplayer]);
tmsg = "$SWWM_MAINCONTROLS";
tmsgtic = gametic+70;
lasttuid = Random[TUID]();
hnd = SWWMHandler(EventHandler.Find("SWWMHandler"));
if ( gameinfo.gametype&GAME_Heretic )
{
c_year = 2171;
@ -281,6 +301,7 @@ Class SWWMKnowledgeBaseMenu : GenericMenu
{
case MKEY_BACK:
MenuSound("menu/democlose");
EventHandler.SendNetworkEvent("swwmclearalltransactions",consoleplayer);
Close();
return true;
case MKEY_PAGEUP:
@ -568,12 +589,14 @@ Class SWWMKnowledgeBaseMenu : GenericMenu
{
// can't use this
if ( invlist[sel0] is 'Ammo' ) return true;
lastuse = invlist[sel0].GetClass();
lastuseamt = invlist[sel0].Amount;
// don't check weapons (or the lamp)
if ( !(invlist[sel0] is 'Weapon') && !(invlist[sel0] is 'SWWMLamp') )
checkuse = gametic+(multiplayer?5:1);
EventHandler.SendNetworkEvent(String.Format("swwmuseitem.%s",invlist[sel0].GetClassName()),consoleplayer);
let t = new("MenuTransaction");
t.uid = GenTUID();
t.type = MenuTransaction.TT_ITEMUSE;
t.result = false;
// don't check weapons, always assume check succeeded
if ( invlist[sel0] is 'Weapon' ) t.result = true;
checklist.Push(t);
EventHandler.SendNetworkEvent(String.Format("swwmuseitem.%s",invlist[sel0].GetClassName()),consoleplayer,t.uid);
}
else if ( (curtab == TAB_STORE) && (storelist.Size() > 0) && (sel0 < storelist.Size()) )
{
@ -639,20 +662,24 @@ Class SWWMKnowledgeBaseMenu : GenericMenu
else if ( sub && (sel0 != -1) && (invlist.Size() > 0) )
{
// trade item
lastuse = invlist[sel1].GetClass();
lastuseamt = invlist[sel1].Amount;
checksend = gametic+(multiplayer?5:1);
EventHandler.SendNetworkEvent(String.Format("swwmtrade.%s",invlist[sel1].GetClassName()),consoleplayer,playerlist[sel0]);
let t = new("MenuTransaction");
t.uid = GenTUID();
t.type = MenuTransaction.TT_ITEMSEND;
t.result = false;
checklist.Push(t);
EventHandler.SendNetworkEvent(String.Format("swwmtrade.%s",invlist[sel1].GetClassName()),consoleplayer,playerlist[sel0],t.uid);
}
}
return true;
case MKEY_CLEAR:
if ( (curtab == TAB_INVENTORY) && (invlist.Size() > 0) )
{
lastuse = invlist[sel0].GetClass();
lastuseamt = invlist[sel0].Amount;
checkdrop = gametic+(multiplayer?5:1);
EventHandler.SendNetworkEvent(String.Format("swwmdropitem.%s",invlist[sel0].GetClassName()),consoleplayer);
let t = new("MenuTransaction");
t.uid = GenTUID();
t.type = MenuTransaction.TT_ITEMDROP;
t.result = false;
checklist.Push(t);
EventHandler.SendNetworkEvent(String.Format("swwmdropitem.%s",invlist[sel0].GetClassName()),consoleplayer,t.uid);
}
else if ( (curtab == TAB_LIBRARY) && sub )
{
@ -764,7 +791,8 @@ Class SWWMKnowledgeBaseMenu : GenericMenu
for ( int i=0; i<invlist.Size(); i++ )
{
if ( !invlist[i] ) continue;
if ( (invlist[i] is 'Ammo') || (invlist[i].Amount > 1) || (!(invlist[i] is 'PuzzleItem') && (invlist[i].MaxAmount > 1)) ) str = String.Format("%dx %s",invlist[i].Amount,invlist[i].GetTag());
if ( invlist[i] is 'Ammo' ) str = String.Format("(%d/%d) %s",invlist[i].Amount,invlist[i].MaxAmount,invlist[i].GetTag());
else if ( (invlist[i].Amount > 1) || (!(invlist[i] is 'PuzzleItem') && (invlist[i].MaxAmount > 1)) ) str = String.Format("%dx %s",invlist[i].Amount,invlist[i].GetTag());
else str = invlist[i].GetTag();
len = fnt.StringWidth(str);
if ( len > longest ) longest = len;
@ -808,7 +836,8 @@ Class SWWMKnowledgeBaseMenu : GenericMenu
for ( int i=0; i<invlist.Size(); i++ )
{
if ( !invlist[i] ) continue;
if ( (invlist[i] is 'Ammo') || (invlist[i].Amount > 1) || (!(invlist[i] is 'PuzzleItem') && (invlist[i].MaxAmount > 1)) ) str = String.Format("%dx %s",invlist[i].Amount,invlist[i].GetTag());
if ( invlist[i] is 'Ammo' ) str = String.Format("(%d/%d) %s",invlist[i].Amount,invlist[i].MaxAmount,invlist[i].GetTag());
else if ( (invlist[i].Amount > 1) || (!(invlist[i] is 'PuzzleItem') && (invlist[i].MaxAmount > 1)) ) str = String.Format("%dx %s",invlist[i].Amount,invlist[i].GetTag());
else str = invlist[i].GetTag();
len = fnt.StringWidth(str);
if ( len > longest ) longest = len;
@ -836,7 +865,8 @@ Class SWWMKnowledgeBaseMenu : GenericMenu
for ( int i=0; i<invlist.Size(); i++ )
{
if ( !invlist[i] ) continue;
if ( (invlist[i] is 'Ammo') || (invlist[i].Amount > 1) || (!(invlist[i] is 'PuzzleItem') && (invlist[i].MaxAmount > 1)) ) str = String.Format("%dx %s",invlist[i].Amount,invlist[i].GetTag());
if ( invlist[i] is 'Ammo' ) str = String.Format("(%d/%d) %s",invlist[i].Amount,invlist[i].MaxAmount,invlist[i].GetTag());
else if ( (invlist[i].Amount > 1) || (!(invlist[i] is 'PuzzleItem') && (invlist[i].MaxAmount > 1)) ) str = String.Format("%dx %s",invlist[i].Amount,invlist[i].GetTag());
else str = invlist[i].GetTag();
len = fnt.StringWidth(str);
if ( len > longest ) longest = len;
@ -880,7 +910,8 @@ Class SWWMKnowledgeBaseMenu : GenericMenu
for ( int i=0; i<invlist.Size(); i++ )
{
if ( !invlist[i] ) continue;
if ( (invlist[i] is 'Ammo') || (invlist[i].Amount > 1) || (!(invlist[i] is 'PuzzleItem') && (invlist[i].MaxAmount > 1)) ) str = String.Format("%dx %s",invlist[i].Amount,invlist[i].GetTag());
if ( invlist[i] is 'Ammo' ) str = String.Format("(%d/%d) %s",invlist[i].Amount,invlist[i].MaxAmount,invlist[i].GetTag());
else if ( (invlist[i].Amount > 1) || (!(invlist[i] is 'PuzzleItem') && (invlist[i].MaxAmount > 1)) ) str = String.Format("%dx %s",invlist[i].Amount,invlist[i].GetTag());
else str = invlist[i].GetTag();
len = fnt.StringWidth(str);
if ( len > longest ) longest = len;
@ -1288,7 +1319,8 @@ Class SWWMKnowledgeBaseMenu : GenericMenu
for ( int i=0; i<invlist.Size(); i++ )
{
if ( !invlist[i] ) continue;
if ( (invlist[i] is 'Ammo') || (invlist[i].Amount > 1) || (!(invlist[i] is 'PuzzleItem') && (invlist[i].MaxAmount > 1)) ) str = String.Format("%dx %s",invlist[i].Amount,invlist[i].GetTag());
if ( invlist[i] is 'Ammo' ) str = String.Format("(%d/%d) %s",invlist[i].Amount,invlist[i].MaxAmount,invlist[i].GetTag());
else if ( (invlist[i].Amount > 1) || (!(invlist[i] is 'PuzzleItem') && (invlist[i].MaxAmount > 1)) ) str = String.Format("%dx %s",invlist[i].Amount,invlist[i].GetTag());
else str = invlist[i].GetTag();
len = fnt.StringWidth(str);
if ( len > longest ) longest = len;
@ -1591,6 +1623,7 @@ Class SWWMKnowledgeBaseMenu : GenericMenu
if ( players[consoleplayer].Health <= 0 )
{
// ded
EventHandler.SendNetworkEvent("swwmclearalltransactions",consoleplayer);
Close();
return;
}
@ -1633,6 +1666,8 @@ Class SWWMKnowledgeBaseMenu : GenericMenu
}
// re-sort by category
qsort_inventory(invlist,0,invlist.Size()-1);
// crop selection
if ( sel0 >= invlist.Size() ) sel0 = max(0,invlist.Size()-1);
}
else if ( (curtab == TAB_STATS) && (sel1 == STAT_KILLS) )
{
@ -1649,6 +1684,8 @@ Class SWWMKnowledgeBaseMenu : GenericMenu
let k = Key(players[consoleplayer].mo.FindInventory(Key.GetKeyType(i)));
if ( k ) invlist.Push(k);
}
// crop selection
if ( sel0 >= invlist.Size() ) sel0 = max(0,invlist.Size()-1);
}
else if ( curtab == TAB_STORE )
{
@ -1732,6 +1769,8 @@ Class SWWMKnowledgeBaseMenu : GenericMenu
}
// re-sort by category
qsort_store(storelist,storeunits,0,storelist.Size()-1);
// crop selection
if ( sel0 >= storelist.Size() ) sel0 = max(0,storelist.Size()-1);
}
else if ( curtab == TAB_LIBRARY )
{
@ -1797,57 +1836,70 @@ Class SWWMKnowledgeBaseMenu : GenericMenu
}
// re-sort by category
qsort_inventory(invlist,0,invlist.Size()-1);
// crop selection
if ( sel1 >= invlist.Size() ) sel1 = max(0,invlist.Size()-1);
}
}
// check if use succeeded
if ( checkuse && (gametic > checkuse) )
// ui->play transaction checks
for ( int i=0; i<checklist.Size(); i++ )
{
checkuse = 0;
int amt = players[consoleplayer].mo.CountInv(lastuse);
if ( amt == lastuseamt )
bool deleteme = false;
for ( int j=0; j<hnd.checklist.Size(); j++ )
{
tmsg = StringTable.Localize("$SWWM_INVFAIL");
tmsgtic = gametic+70;
MenuSound("menu/noinvuse");
}
else
{
MenuSound(GetDefaultByType(lastuse).UseSound);
if ( (amt == 0) && (sel0 >= invlist.Size()) )
sel0 = max(0,sel0-1);
}
}
// check if drop succeeded
if ( checkdrop && (gametic > checkdrop) )
{
checkdrop = 0;
int amt = players[consoleplayer].mo.CountInv(lastuse);
if ( amt == lastuseamt )
{
tmsg = StringTable.Localize("$SWWM_INVNDROP");
tmsgtic = gametic+70;
MenuSound("menu/noinvuse");
}
else if ( (amt == 0) && (sel0 >= invlist.Size()) )
sel0 = max(0,sel0-1);
}
// check if trade succeeded
if ( checksend && (gametic > checksend) )
{
checksend = 0;
int amt = players[consoleplayer].mo.CountInv(lastuse);
if ( amt == lastuseamt )
{
tmsg = StringTable.Localize("$SWWM_TRADEFULL");
tmsgtic = gametic+70;
MenuSound("menu/noinvuse");
}
else
{
MenuSound("menu/demosel");
if ( (amt == 0) && (sel1 >= invlist.Size()) )
sel1 = max(0,sel1-1);
if ( hnd.checklist[j].uid != checklist[i].uid ) continue;
if ( checklist[i].type == MenuTransaction.TT_ITEMUSE )
{
// check if use succeeded
if ( checklist[i].result || hnd.checklist[j].result )
{
// only play use sound if game isn't frozen
if ( !multiplayer && (menuactive == Menu.On) )
{
// if it's a weapon, play the select sound
let w = (Class<Weapon>)(hnd.checklist[j].used);
if ( w )
{
// play if actually switching
if ( hnd.checklist[j].result ) MenuSound(GetDefaultByType(w).UpSound);
}
else MenuSound(GetDefaultByType(hnd.checklist[j].used).UseSound);
}
}
else
{
tmsg = StringTable.Localize("$SWWM_INVFAIL");
tmsgtic = gametic+70;
MenuSound("menu/noinvuse");
}
}
else if ( checklist[i].type == MenuTransaction.TT_ITEMDROP )
{
// check if drop succeeded
if ( !hnd.checklist[j].result )
{
tmsg = StringTable.Localize("$SWWM_INVNDROP");
tmsgtic = gametic+70;
MenuSound("menu/noinvuse");
}
}
else if ( checklist[i].type == MenuTransaction.TT_ITEMSEND )
{
// check if trade succeeded
if ( !hnd.checklist[j].result )
{
tmsg = StringTable.Localize("$SWWM_TRADEFULL");
tmsgtic = gametic+70;
MenuSound("menu/noinvuse");
}
else MenuSound("menu/demosel");
}
EventHandler.SendNetworkEvent("swwmcleartransaction",checklist[i].uid,consoleplayer);
deleteme = true;
break;
}
if ( !deleteme ) continue;
checklist.Delete(i);
i--;
}
}
@ -1893,6 +1945,7 @@ Class SWWMKnowledgeBaseMenu : GenericMenu
if( (ikey[0] && (ev.keystring == mkey[0])) || (ikey[1] && (ev.keystring == mkey[1])) )
{
MenuSound("menu/democlose");
EventHandler.SendNetworkEvent("swwmclearalltransactions",consoleplayer);
Close();
return true;
}
@ -1933,41 +1986,41 @@ Class SWWMKnowledgeBaseMenu : GenericMenu
break;
case UIEvent.Type_LButtonDown:
isrclick = false;
return Super.OnUIEvent(ev);
// copy over what base menus do for L click
// but ignore back button, since we don't use it
bool lres = MouseEvent(MOUSE_Click,ev.MouseX,ev.MouseY);
if ( lres ) SetCapture(true);
return lres;
break;
case UIEvent.Type_RButtonDown:
isrclick = true;
// copy over what base menus do for L click
int y = ev.MouseY;
bool res = MouseEventBack(MOUSE_Click,ev.MouseX,y);
if ( res ) y = -1;
res |= MouseEvent(MOUSE_Click,ev.MouseX,y);
if ( res ) SetCapture(true);
return false;
// same as L click
bool rres = MouseEvent(MOUSE_Click,ev.MouseX,ev.MouseY);
if ( rres ) SetCapture(true);
return rres;
break;
case UIEvent.Type_LButtonUp:
case UIEvent.Type_RButtonUp:
// copy over what base menus do for L release
// copy over what base menus do for release
// but ignore back button, since we don't use it
if ( mMouseCapture )
{
SetCapture(false);
int y = ev.MouseY;
bool res = MouseEventBack(MOUSE_Release,ev.MouseX,y);
if ( res ) y = -1;
res |= MouseEvent(MOUSE_Release,ev.MouseX,y);
return MouseEvent(MOUSE_Release,ev.MouseX,ev.MouseY);
}
return false;
break;
case UIEvent.Type_MouseMove:
// store coords
// store coords beforehand
curmouse = (ev.MouseX,ev.MouseY);
if ( mMouseCapture || (m_use_mouse == 1) )
return MouseEvent(MOUSE_Move,ev.MouseX,ev.MouseY);
break;
}
return Super.OnUIEvent(ev);
return false;
}
override void Drawer()
{
Super.Drawer();
Font fnt = LangFont(TewiFont);
String str;
double hs;

View file

@ -46,10 +46,16 @@ Class Demolitionist : PlayerPawn
int deadtimer;
transient int revivefail;
transient int bumptic;
Actor selflight;
Actor oldencroached;
Vector3 oldencroachedpos;
SWWMItemSense itemsense;
int itemsense_cnt;
int lastsense;
Default
{
Speed 1;
@ -335,6 +341,21 @@ Class Demolitionist : PlayerPawn
}
fuelcooldown = max(20,fuelcooldown);
}
void SenseItems()
{
if ( level.maptime < lastsense+5 )
return;
lastsense = level.maptime;
let thesight = FindInventory("Omnisight");
let bt = BlockThingsIterator.Create(self,1200);
while ( bt.Next() )
{
let i = Inventory(bt.Thing);
if ( !i || i.bINVISIBLE || !i.bSPECIAL || i.Owner || !SWWMUtility.SphereIntersect(i,pos,thesight?1200:800) ) continue;
if ( !thesight && !CheckSight(i) ) continue;
SWWMItemSense.Spawn(self,i);
}
}
void CheckUnderwaterAmb( bool restore = false )
{
Vector3 headpos = Vec3Offset(0,0,player.viewheight);
@ -502,6 +523,7 @@ Class Demolitionist : PlayerPawn
}
else mystats.swimdist += traveldist;
CheckUnderwaterAmb();
if ( player.cmd.buttons&BT_USER3 ) SenseItems();
if ( vel.length() > mystats.topspeed ) mystats.topspeed = vel.length();
if ( !myvoice ) myvoice = CVar.GetCVar('swwm_voicetype',player);
if ( !mute ) mute = CVar.GetCVar('swwm_mutevoice',player);
@ -593,7 +615,7 @@ Class Demolitionist : PlayerPawn
dashcooldown = max(0,dashcooldown-1);
boostcooldown = max(0,boostcooldown-1);
if ( fuelcooldown <= 0 )
dashfuel = min(240.,dashfuel+max(dashfuel*.01,.05));
dashfuel = min(240.,dashfuel+max(dashfuel*.015,.1));
if ( (dashboost > 0.) && (InStateSequence(CurState,FindState("Dash")) || (InStateSequence(CurState,FindState("Jump")) && player.cmd.buttons&BT_JUMP)) )
dashsnd = true;
else
@ -634,6 +656,7 @@ Class Demolitionist : PlayerPawn
A_QuakeEx(4,4,4,10,0,128,"",QF_RELATIVE|QF_SCALEDOWN);
A_StartSound("demolitionist/bump",CHAN_DAMAGE,CHANF_OVERLAP);
a.A_StartSound("demolitionist/bump",CHAN_DAMAGE,CHANF_OVERLAP);
bumptic = gametic+int(5+spd/4.);
if ( (diff.z < a.height) && (lastvelz >= -25) && (a.bDONTTHRUST || (a.Mass >= Mass*1.5)) )
{
if ( bumped ) continue;

View file

@ -236,7 +236,7 @@ Class GhostArtifactX : Actor
+NOCLIP;
+DONTSPLASH;
+NOINTERACTION;
Radius 0.1;
Radius .1;
Height 0;
+FLOATBOB;
FloatBobStrength 0.25;
@ -249,7 +249,8 @@ Class GhostArtifactX : Actor
Destroy();
return;
}
Warp(target,flags:WARPF_COPYINTERPOLATION|WARPF_NOCHECKPOSITION);
Warp(target,flags:WARPF_INTERPOLATE|WARPF_NOCHECKPOSITION);
FloatBobPhase = target.FloatBobPhase;
bInvisible = target.bInvisible||!target.InStateSequence(target.CurState,target.FindState("Spawn"));
}
States

View file

@ -887,7 +887,7 @@ Class BiosparkComboImpact : Actor
{
Super.PostBeginPlay();
A_AlertMonsters(6000);
SWWMHandler.DoExplosion(self,bAMBUSH?(1600+Args[0]*100):1500,480000,bAMBUSH?1200:700,bAMBUSH?900:400);
SWWMHandler.DoExplosion(self,bAMBUSH?(700+Args[0]*100):300,bAMBUSH?480000:200000,bAMBUSH?800:400,bAMBUSH?400:200);
A_QuakeEx(9,9,9,25,0,2000,"",QF_RELATIVE|QF_SCALEDOWN,falloff:600,rollIntensity:1.5);
A_StartSound("biospark/bighit",CHAN_ITEM,attenuation:.4);
A_StartSound("biospark/bighit",CHAN_WEAPON,attenuation:.3);
@ -930,8 +930,8 @@ Class BiosparkComboImpact : Actor
s.target = target;
s.angle = ang;
s.pitch = pt;
s.ReactionTime += Random[Sparkster](0,10);
if ( bAMBUSH ) s.ReactionTime += 4+Args[0]*4;
s.ReactionTime += Random[Sparkster](0,5);
if ( bAMBUSH ) s.ReactionTime += 8+Args[0]*4;
}
if ( bAMBUSH )
{
@ -950,18 +950,13 @@ Class BiosparkComboImpact : Actor
}
void A_SparkSubExpl()
{
double mx = bAMBUSH?30.:20.;
double mx = bAMBUSH?40.:30.;
special1++;
if ( special1 > mx ) return;
double factor = (mx-special1)/mx;
double invfct = 1.-factor;
if ( bAMBUSH )
{
factor *= 1.5;
invfct *= 1.5;
}
SWWMHandler.DoExplosion(self,(1500+Args[0]*50)*factor,0.,600*invfct);
SWWMHandler.DoExplosion(self,0.,-10000*factor,800*invfct);
SWWMHandler.DoExplosion(self,(bAMBUSH?(500+Args[0]*50):200)*factor,0.,(bAMBUSH?900.:300.)*invfct);
SWWMHandler.DoExplosion(self,0.,-12000*factor,(bAMBUSH?1500:500)*invfct);
int numpt = int(Random[ExploS](8,16)*factor);
for ( int i=0; i<numpt; i++ )
{
@ -979,7 +974,7 @@ Class BiosparkComboImpact : Actor
{
double ang = FRandom[ExploS](0,360);
double pt = FRandom[ExploS](-90,90);
double dist = (FRandom[ExploS](5,20)+100*invfct);
double dist = (FRandom[ExploS](5,20)+60*invfct);
if ( LineTrace(ang,dist,pt,TRF_THRUACTORS|TRF_THRUHITSCAN) ) continue;
Vector3 ofs = (cos(ang)*cos(pt),sin(ang)*cos(pt),-sin(pt))*dist;
Vector3 spos = level.Vec3Offset(pos,ofs);
@ -1010,10 +1005,11 @@ Class BiosparkComboImpact : Actor
void A_SparkSubExpl2()
{
special2++;
if ( (special2 > 30) || !(special2%2) ) return;
int numpt = Random[Sparkster](0,30-special2);
int mx = bAMBUSH?40:30;
if ( (special2 > mx) || !(special2%2) ) return;
int numpt = Random[Sparkster](0,mx-special2);
double ang, pt;
double mul = bAMBUSH?8:4;
double mul = bAMBUSH?8:3;
for ( int i=0; i<numpt; i++ )
{
ang = FRandom[Sparkster](0,360);
@ -1578,7 +1574,7 @@ Class BiosparkArc : Actor
States
{
Spawn:
XZW1 # 1 Bright;
XZW1 # 0 Bright;
XZW1 # 1 Bright A_Trace();
XZW1 # 1 Bright A_Spread("biospark/bigarc",.6,1);
XZW1 # 1 Bright A_FadeOut(.05);
@ -1597,7 +1593,7 @@ Class BiosparkArcSmall : BiosparkArc
States
{
Spawn:
XZW1 # 1 Bright;
XZW1 # 0 Bright;
XZW1 # 1 Bright A_Trace();
XZW1 # 1 Bright A_Spread("biospark/arc",2.,0);
XZW1 # 1 Bright A_FadeOut(.1);
@ -1616,7 +1612,7 @@ Class BiosparkArcBig : BiosparkArc
States
{
Spawn:
XZW1 # 1 Bright;
XZW1 # 0 Bright;
XZW1 # 1 Bright A_Trace();
XZW1 # 1 Bright A_Spread("biospark/hugearc",.4,2);
XZW1 # 1 Bright A_FadeOut(.025);
@ -1871,7 +1867,7 @@ Class BiosparkCore : Actor
s.vel = pvel+vel*.5;
s.SetShade(Color(4,5,2)*Random[ExploS](40,50));
s.A_SetRenderStyle(s.alpha*.4,STYLE_AddShaded);
s.scale *= 2.;
s.scale *= 4.;
s.bAMBUSH = true;
}
Wait;