diff --git a/CREDITS b/CREDITS new file mode 100644 index 0000000..692a39f --- /dev/null +++ b/CREDITS @@ -0,0 +1,19 @@ +Sprites by Kiri. +(Deployed battery sprite modified from id Software original sprite.) + +Code by Kiri. + +Jokes by Twitch chat (thanks, Drikanis), so blame them. + +prettyFist for general advisement. + +People keeping me company in VC right now: + - Clance + - prettyFist + - Generic Firedemon + - Jenin + - Mia-chan + - Squarepog + - Fay + + diff --git a/cvarinfo.txt b/cvarinfo.txt index f17899a..f8e3a92 100644 --- a/cvarinfo.txt +++ b/cvarinfo.txt @@ -1 +1 @@ -server int snektech_spawnflags = 1; +server int snektech_spawnflags = 3; diff --git a/gldefs.txt b/gldefs.txt index aa0b1f6..48be2d1 100644 --- a/gldefs.txt +++ b/gldefs.txt @@ -1,3 +1,6 @@ +// ---------------------------------------------------------------------- +// Gretchen counter brightmaps + brightmap sprite kgcma0 { map "sprites/gretchencounter/bright_kgcma0.png" @@ -33,3 +36,27 @@ brightmap sprite kgcpb0 map "sprites/gretchencounter/bright_kgcpb0.png" disablefullbright } + +// ---------------------------------------------------------------------- +// Jumper cables brightmaps + +brightmap sprite jmppa0 +{ + map "sprites/bright_jmpr_1.png" + disablefullbright +} + +brightmap sprite jmppb0 +{ + map "sprites/bright_jmpr_2.png" + disablefullbright +} + +brightmap sprite jmppc0 +{ + map "sprites/bright_jmpr_3.png" + disablefullbright +} + + + diff --git a/mapinfo.txt b/mapinfo.txt index 85e6a88..4358d89 100644 --- a/mapinfo.txt +++ b/mapinfo.txt @@ -1,5 +1,6 @@ gameinfo { AddEventHandlers = "SnekTechEventHandler" + AddEventHandlers = "JumperCablesMapLoader" } diff --git a/menudef.txt b/menudef.txt index b1551b2..24f82a3 100644 --- a/menudef.txt +++ b/menudef.txt @@ -8,5 +8,6 @@ OptionMenu "SnekTechMenu" Title "SnekTech Discount Party Pack" StaticText "----- Item Spawns -----", "Teal" FlagOption "Gretchen Counter", "snektech_spawnflags", "YesNo", 0 + FlagOption "Wiring Bypass Kit", "snektech_spawnflags", "YesNo", 1 } diff --git a/sprites/jumpercables/bright_jmpr_1.png b/sprites/jumpercables/bright_jmpr_1.png new file mode 100644 index 0000000..6ad7d19 Binary files /dev/null and b/sprites/jumpercables/bright_jmpr_1.png differ diff --git a/sprites/jumpercables/bright_jmpr_2.png b/sprites/jumpercables/bright_jmpr_2.png new file mode 100644 index 0000000..5916670 Binary files /dev/null and b/sprites/jumpercables/bright_jmpr_2.png differ diff --git a/sprites/jumpercables/bright_jmpr_3.png b/sprites/jumpercables/bright_jmpr_3.png new file mode 100644 index 0000000..fc8c1de Binary files /dev/null and b/sprites/jumpercables/bright_jmpr_3.png differ diff --git a/sprites/jumpercables/jmila0.png b/sprites/jumpercables/jmila0.png new file mode 100644 index 0000000..f5c0720 Binary files /dev/null and b/sprites/jumpercables/jmila0.png differ diff --git a/sprites/jumpercables/jmilb0.png b/sprites/jumpercables/jmilb0.png new file mode 100644 index 0000000..59c1bd3 Binary files /dev/null and b/sprites/jumpercables/jmilb0.png differ diff --git a/sprites/jumpercables/jmilc0.png b/sprites/jumpercables/jmilc0.png new file mode 100644 index 0000000..a67ac1b Binary files /dev/null and b/sprites/jumpercables/jmilc0.png differ diff --git a/sprites/jumpercables/jmild0.png b/sprites/jumpercables/jmild0.png new file mode 100644 index 0000000..a5bb720 Binary files /dev/null and b/sprites/jumpercables/jmild0.png differ diff --git a/sprites/jumpercables/jmile0.png b/sprites/jumpercables/jmile0.png new file mode 100644 index 0000000..2d6a73c Binary files /dev/null and b/sprites/jumpercables/jmile0.png differ diff --git a/sprites/jumpercables/jmilf0.png b/sprites/jumpercables/jmilf0.png new file mode 100644 index 0000000..efec67e Binary files /dev/null and b/sprites/jumpercables/jmilf0.png differ diff --git a/sprites/jumpercables/jmilg0.png b/sprites/jumpercables/jmilg0.png new file mode 100644 index 0000000..43eff18 Binary files /dev/null and b/sprites/jumpercables/jmilg0.png differ diff --git a/sprites/jumpercables/jmilh0.png b/sprites/jumpercables/jmilh0.png new file mode 100644 index 0000000..1abfbf6 Binary files /dev/null and b/sprites/jumpercables/jmilh0.png differ diff --git a/sprites/jumpercables/jmili0.png b/sprites/jumpercables/jmili0.png new file mode 100644 index 0000000..064bf3e Binary files /dev/null and b/sprites/jumpercables/jmili0.png differ diff --git a/sprites/jumpercables/jmilj0.png b/sprites/jumpercables/jmilj0.png new file mode 100644 index 0000000..3cfa799 Binary files /dev/null and b/sprites/jumpercables/jmilj0.png differ diff --git a/sprites/jumpercables/jmilk0.png b/sprites/jumpercables/jmilk0.png new file mode 100644 index 0000000..c792543 Binary files /dev/null and b/sprites/jumpercables/jmilk0.png differ diff --git a/sprites/jumpercables/jmill0.png b/sprites/jumpercables/jmill0.png new file mode 100644 index 0000000..b4d8d28 Binary files /dev/null and b/sprites/jumpercables/jmill0.png differ diff --git a/sprites/jumpercables/jmilm0.png b/sprites/jumpercables/jmilm0.png new file mode 100644 index 0000000..9a56e73 Binary files /dev/null and b/sprites/jumpercables/jmilm0.png differ diff --git a/sprites/jumpercables/jmiln0.png b/sprites/jumpercables/jmiln0.png new file mode 100644 index 0000000..f1a30b5 Binary files /dev/null and b/sprites/jumpercables/jmiln0.png differ diff --git a/sprites/jumpercables/jmilo0.png b/sprites/jumpercables/jmilo0.png new file mode 100644 index 0000000..aa12172 Binary files /dev/null and b/sprites/jumpercables/jmilo0.png differ diff --git a/sprites/jumpercables/jmilp0.png b/sprites/jumpercables/jmilp0.png new file mode 100644 index 0000000..4f698cd Binary files /dev/null and b/sprites/jumpercables/jmilp0.png differ diff --git a/sprites/jumpercables/jmira0.png b/sprites/jumpercables/jmira0.png new file mode 100644 index 0000000..4d5b59c Binary files /dev/null and b/sprites/jumpercables/jmira0.png differ diff --git a/sprites/jumpercables/jmirb0.png b/sprites/jumpercables/jmirb0.png new file mode 100644 index 0000000..7a180c0 Binary files /dev/null and b/sprites/jumpercables/jmirb0.png differ diff --git a/sprites/jumpercables/jmirc0.png b/sprites/jumpercables/jmirc0.png new file mode 100644 index 0000000..b31773f Binary files /dev/null and b/sprites/jumpercables/jmirc0.png differ diff --git a/sprites/jumpercables/jmird0.png b/sprites/jumpercables/jmird0.png new file mode 100644 index 0000000..d32078e Binary files /dev/null and b/sprites/jumpercables/jmird0.png differ diff --git a/sprites/jumpercables/jmire0.png b/sprites/jumpercables/jmire0.png new file mode 100644 index 0000000..88b28f3 Binary files /dev/null and b/sprites/jumpercables/jmire0.png differ diff --git a/sprites/jumpercables/jmirf0.png b/sprites/jumpercables/jmirf0.png new file mode 100644 index 0000000..d41a498 Binary files /dev/null and b/sprites/jumpercables/jmirf0.png differ diff --git a/sprites/jumpercables/jmirg0.png b/sprites/jumpercables/jmirg0.png new file mode 100644 index 0000000..4e3609c Binary files /dev/null and b/sprites/jumpercables/jmirg0.png differ diff --git a/sprites/jumpercables/jmirh0.png b/sprites/jumpercables/jmirh0.png new file mode 100644 index 0000000..a6edf7d Binary files /dev/null and b/sprites/jumpercables/jmirh0.png differ diff --git a/sprites/jumpercables/jmiri0.png b/sprites/jumpercables/jmiri0.png new file mode 100644 index 0000000..65f94ba Binary files /dev/null and b/sprites/jumpercables/jmiri0.png differ diff --git a/sprites/jumpercables/jmirj0.png b/sprites/jumpercables/jmirj0.png new file mode 100644 index 0000000..d3852ec Binary files /dev/null and b/sprites/jumpercables/jmirj0.png differ diff --git a/sprites/jumpercables/jmirk0.png b/sprites/jumpercables/jmirk0.png new file mode 100644 index 0000000..6bc2b1e Binary files /dev/null and b/sprites/jumpercables/jmirk0.png differ diff --git a/sprites/jumpercables/jmirl0.png b/sprites/jumpercables/jmirl0.png new file mode 100644 index 0000000..a0cf3db Binary files /dev/null and b/sprites/jumpercables/jmirl0.png differ diff --git a/sprites/jumpercables/jmirm0.png b/sprites/jumpercables/jmirm0.png new file mode 100644 index 0000000..ddb3060 Binary files /dev/null and b/sprites/jumpercables/jmirm0.png differ diff --git a/sprites/jumpercables/jmirn0.png b/sprites/jumpercables/jmirn0.png new file mode 100644 index 0000000..7ecba86 Binary files /dev/null and b/sprites/jumpercables/jmirn0.png differ diff --git a/sprites/jumpercables/jmiro0.png b/sprites/jumpercables/jmiro0.png new file mode 100644 index 0000000..56e3673 Binary files /dev/null and b/sprites/jumpercables/jmiro0.png differ diff --git a/sprites/jumpercables/jmirp0.png b/sprites/jumpercables/jmirp0.png new file mode 100644 index 0000000..d62940b Binary files /dev/null and b/sprites/jumpercables/jmirp0.png differ diff --git a/sprites/jumpercables/jmpia0.png b/sprites/jumpercables/jmpia0.png new file mode 100644 index 0000000..66d317e Binary files /dev/null and b/sprites/jumpercables/jmpia0.png differ diff --git a/sprites/jumpercables/jmpib0.png b/sprites/jumpercables/jmpib0.png new file mode 100644 index 0000000..83f4294 Binary files /dev/null and b/sprites/jumpercables/jmpib0.png differ diff --git a/sprites/jumpercables/jmpic0.png b/sprites/jumpercables/jmpic0.png new file mode 100644 index 0000000..935bdb7 Binary files /dev/null and b/sprites/jumpercables/jmpic0.png differ diff --git a/sprites/jumpercables/jmpid0.png b/sprites/jumpercables/jmpid0.png new file mode 100644 index 0000000..bed511c Binary files /dev/null and b/sprites/jumpercables/jmpid0.png differ diff --git a/sprites/jumpercables/jmpie0.png b/sprites/jumpercables/jmpie0.png new file mode 100644 index 0000000..b7af2d1 Binary files /dev/null and b/sprites/jumpercables/jmpie0.png differ diff --git a/sprites/jumpercables/jmpif0.png b/sprites/jumpercables/jmpif0.png new file mode 100644 index 0000000..fe31487 Binary files /dev/null and b/sprites/jumpercables/jmpif0.png differ diff --git a/sprites/jumpercables/jmpig0.png b/sprites/jumpercables/jmpig0.png new file mode 100644 index 0000000..810b806 Binary files /dev/null and b/sprites/jumpercables/jmpig0.png differ diff --git a/sprites/jumpercables/jmpja0.png b/sprites/jumpercables/jmpja0.png new file mode 100644 index 0000000..776abfe Binary files /dev/null and b/sprites/jumpercables/jmpja0.png differ diff --git a/sprites/jumpercables/jmpjb0.png b/sprites/jumpercables/jmpjb0.png new file mode 100644 index 0000000..48391c4 Binary files /dev/null and b/sprites/jumpercables/jmpjb0.png differ diff --git a/sprites/jumpercables/jmpjc0.png b/sprites/jumpercables/jmpjc0.png new file mode 100644 index 0000000..a406760 Binary files /dev/null and b/sprites/jumpercables/jmpjc0.png differ diff --git a/sprites/jumpercables/jmpjd0.png b/sprites/jumpercables/jmpjd0.png new file mode 100644 index 0000000..2af9709 Binary files /dev/null and b/sprites/jumpercables/jmpjd0.png differ diff --git a/sprites/jumpercables/jmpje0.png b/sprites/jumpercables/jmpje0.png new file mode 100644 index 0000000..de6f482 Binary files /dev/null and b/sprites/jumpercables/jmpje0.png differ diff --git a/sprites/jumpercables/jmpjf0.png b/sprites/jumpercables/jmpjf0.png new file mode 100644 index 0000000..fef03d7 Binary files /dev/null and b/sprites/jumpercables/jmpjf0.png differ diff --git a/sprites/jumpercables/jmpjg0.png b/sprites/jumpercables/jmpjg0.png new file mode 100644 index 0000000..dd90f1c Binary files /dev/null and b/sprites/jumpercables/jmpjg0.png differ diff --git a/sprites/jumpercables/jmpka0.png b/sprites/jumpercables/jmpka0.png new file mode 100644 index 0000000..8b902dc Binary files /dev/null and b/sprites/jumpercables/jmpka0.png differ diff --git a/sprites/jumpercables/jmppa0.png b/sprites/jumpercables/jmppa0.png new file mode 100644 index 0000000..11a1d82 Binary files /dev/null and b/sprites/jumpercables/jmppa0.png differ diff --git a/sprites/jumpercables/jmppb0.png b/sprites/jumpercables/jmppb0.png new file mode 100644 index 0000000..f1fb611 Binary files /dev/null and b/sprites/jumpercables/jmppb0.png differ diff --git a/sprites/jumpercables/jmppc0.png b/sprites/jumpercables/jmppc0.png new file mode 100644 index 0000000..cbf2d8c Binary files /dev/null and b/sprites/jumpercables/jmppc0.png differ diff --git a/sprites/jumpercables/jmpra0.png b/sprites/jumpercables/jmpra0.png new file mode 100644 index 0000000..1208da4 Binary files /dev/null and b/sprites/jumpercables/jmpra0.png differ diff --git a/textures.txt b/textures.txt index 479051e..fb70ebc 100644 --- a/textures.txt +++ b/textures.txt @@ -1,3 +1,6 @@ +// ---------------------------------------------------------------------- +// Gretchen Counter + sprite KGCPA0, 32, 32 { offset 16, 32 patch KGCPA0,0,0 { } @@ -7,3 +10,53 @@ sprite KGCPB0, 32, 32 { offset 16, 32 patch KGCPB0,0,0 { } } + +// ---------------------------------------------------------------------- +// Jumper cables + +sprite JMPRA0, 49, 43 { + offset 24, 21 + patch JMPRA0,0,0 { } +} + +sprite JMPRB0, 49, 43 { + offset 24, 21 + patch JMPRA0,0,0 { translation "112:120=160:167" } +} + +sprite JMPRC0, 49, 43 { + offset 24, 21 + patch JMPRA0,0,0 { translation "112:120=32:47" } +} + +sprite JMPRD0, 49, 43 { + offset 24, 21 + patch JMPRA0,0,0 { translation "112:120=96:111" } +} + +sprite JMPKA0, 48, 32 { + offset 24, 16 + patch JMPKA0,0,0 { } +} + +// Weapon sprites. +// +// Note that there's a corresponding offset in the ledd_left_indicator +// and ledd_right_indicator states in object itself, which offset the +// text into position. + +sprite JMPPA0, 320, 200 { + offset 0, 32 + patch JMPPA0,0,0 { } +} + +sprite JMPPB0, 320, 200 { + offset 0, 32 + patch JMPPB0,0,0 { } +} + +sprite JMPPC0, 320, 200 { + offset 0, 32 + patch JMPPC0,0,0 { } +} + diff --git a/zscript.zs b/zscript.zs index 2937a44..1ca7d9e 100644 --- a/zscript.zs +++ b/zscript.zs @@ -1,4 +1,5 @@ version "4.10" #include "zscript/snektech.zs" +#include "zscript/jumpercables.zs" #include "zscript/gretchencounter.zs" diff --git a/zscript/gretchencounter.zs b/zscript/gretchencounter.zs index b988cea..cdec994 100644 --- a/zscript/gretchencounter.zs +++ b/zscript/gretchencounter.zs @@ -160,7 +160,6 @@ class GretchenCounter : HDWeapon KGCM B 1 { A_Overlay(355, "needle_indicator"); A_OverlayPivotAlign(355, PSPA_CENTER, PSPA_BOTTOM); - // invoker.UpdateDisplay(); updateOverlay(); // USER3 = MagManager. @@ -178,7 +177,7 @@ class GretchenCounter : HDWeapon KGCM # 1 { invoker.weaponstatus[KGC_ACTIVE] = !invoker.weaponstatus[KGC_ACTIVE]; - A_PlaySound("kiri/gretchencounter_onoff"); + A_StartSound("kiri/gretchencounter_onoff"); updateOverlay(); } @@ -295,7 +294,6 @@ class GretchenCounter : HDWeapon statusBar.DI_SCREEN_CENTER_BOTTOM, Font.CR_DARKGRAY); } - } bool GetIsActive() @@ -331,28 +329,7 @@ class GretchenCounter : HDWeapon referenceActor = self; } - // ThinkerIterator iter = ThinkerIterator.Create("BFGNecroShard"); - // Actor mo; - // int shardCount = 0; - // float totalReading = 0.0; - // while(mo = BFGNecroShard(iter.Next())) - // { - // //shardCount++; - // float dist = Distance3D(mo); - - // // Convert to "meters" (with a minimum). - // if(dist < 32) { - // dist = 32; - // } - // dist /= 32.0; - - // // // Arbitrary scaling. - // // dist /= 16.0; - - // totalReading += 1.0 / (dist * dist); - // shardCount += 1; - // } - + // Get the actual reading. float totalReading = 0.0; if(GetIsActive()) { totalReading = @@ -360,63 +337,37 @@ class GretchenCounter : HDWeapon GetReadingForType("HDBarrel", 2.0); } - // lastReading = totalReading * 0.01 + lastReading * 0.99; - float pct_reading = lastReading * 2000.0; lastReading = totalReading; + // Make clicky noises if we're getting readings. float r = frandom(0.0, 1.0); if(r < pct_reading && GetIsActive()) { - // console.printf("test: %f %f", r, pct_reading); referenceActor.A_StartSound("kiri/gretchencounter_click"); } - - // if(pct_reading > 1.0) { - // pct_reading = 1.0; - // } - - - // String meter_str = ""; - // float k; - // for(k = 0.0; k < 1.0; k += 0.02) { - // if(k < pct_reading) { - // meter_str = meter_str.."#"; - // } else { - // meter_str = meter_str.."_"; - // } - // } - - // if(pct_reading > 1.0) { - // pct_reading = 1.0; - // } - // A_OverlayRotate(355, - // angle_min + (angle_max - angle_min) * (1.0 - pct_reading)); - - + // Apply some physics to the needle rotation. angularvelocity += pct_reading - needlePosition; angularvelocity *= 0.97; + // Check to see if the needle was at max last frame. If it + // wasn't at max before, and it is now, we need to start + // beeping. bool wasNeedleAtMax = (needlePosition >= 0.9); needlePosition += angularvelocity * 0.1; needlePosition = clamp(needlePosition, 0.0, 1.0); - - // console.printf("Ang vel %f", angularvelocity); - // console.printf("Shard count: [%s] %f", meter_str, pct_reading); - - + // Play a "beep" if the needle is at max, and it's either been + // long enough or we weren't at max before. Make it start and + // stop. framesSinceLastBeep++; - // if(GetIsActive()) - { - if(!wasNeedleAtMax || framesSinceLastBeep > 15) { - if(needlePosition >= 0.9) { - referenceActor.A_StartSound("kiri/gretchencounter_blip"); - framesSinceLastBeep = 0; - } + if(!wasNeedleAtMax || framesSinceLastBeep > 15) { + if(needlePosition >= 0.9) { + referenceActor.A_StartSound("kiri/gretchencounter_blip"); + framesSinceLastBeep = 0; } } } diff --git a/zscript/jumpercables.zs b/zscript/jumpercables.zs new file mode 100644 index 0000000..4848e3a --- /dev/null +++ b/zscript/jumpercables.zs @@ -0,0 +1,660 @@ +const HDLD_KIRI_JUMPERCABLES = "jmp"; + +const jumperCablesRaycastRange = 48; // Same range as the DERP. +const jumperCablesFixRange = 48; // Maximum distance to a broken linedef to fix, from the raycast hit. + +class JumperCablesMapLoader : EventHandler +{ + Map originalLinedefSpecials2; + Array deployedCables; + bool worldScanCompleted; + + static JumperCablesMapLoader Get() + { + JumperCablesMapLoader loader; + loader = JumperCablesMapLoader(EventHandler.Find("JumperCablesMapLoader")); + return loader; + } + + override void WorldUnloaded(WorldEvent e) + { + JumperCablesMapLoader loader = Get(); + + // Clear out anything from the last level. + deployedCables.Clear(); + loader.originalLinedefSpecials2.Clear(); + worldScanCompleted = false; + } + + override void WorldTick() + { + JumperCablesMapLoader loader = Get(); + + if(!loader.worldScanCompleted) { + + // Go through all the linedefs and make note of what they're + // supposed to do. + for(int k = 0; k < level.Lines.size(); k++) { + Line line = level.Lines[k]; + if(line.special != 0) { + loader.originalLinedefSpecials2.Insert(line.index(), line.special); + } + } + + loader.worldScanCompleted = true; + } + } + + override void WorldLineActivated(WorldEvent e) + { + // Is this line affected by a battery? + for(int cableIndex = 0; cableIndex < deployedCables.size(); cableIndex++) { + if(deployedCables[cableIndex].lineDefIndex == e.ActivatedLine.index()) { + // Yes. Deplete the battery. + deployedCables[cableIndex].DecrementBattery(); + break; + } + } + } + + void RegisterCables(JumperCablesDeployed cableActor) + { + if(deployedCables.Find(cableActor) == deployedCables.size()) { + deployedCables.Push(cableActor); + } + } + + void UnregisterCables(JumperCablesDeployed cableActor) + { + int index = deployedCables.find(cableActor); + if(index != deployedCables.size()) { + deployedCables.delete(index); + } + } +} + +class JumperCablesDeployed : HDUPK +{ + int lineDefIndex; + int charges; + + default + { + radius 2; + height 4; + +SpriteAngle; + Scale 0.4; + } + + states + { + spawn: + JMPR CABD -1; + stop; + } + + override void PostBeginPlay() + { + bNoGravity = true; + + // Register us with the global event handler so we can + // respond to the linedef getting used. + JumperCablesMapLoader loader = JumperCablesMapLoader.Get(); + loader.RegisterCables(self); + + UpdateSprite(); + } + + void SetWallSprite(Vector2 lineDir) + { + bFlatSprite = false; + bWallSprite = true; + A_SetAngle(atan2(lineDir) + 90); + } + + void SetFlatSprite(float angle) + { + bFlatSprite = true; + bWallSprite = false; + A_SetAngle(angle); + } + + void UpdateSprite() + { + // Charge levels correspond to battery sprite charge levels. + if(charges > 13) { + frame = 0; + } else if(charges > 6) { + frame = 1; + } else if(charges > 0) { + frame = 2; + } else { + frame = 3; + } + } + + void DecrementBattery() + { + charges -= 1; + // Console.printf("battery used, now: %d", charges); + if(charges <= 0) { + charges = 0; + DespawnToBattery(); + } + + UpdateSprite(); + } + + void DespawnToBattery() + { + // Re-break the linedef. + level.Lines[lineDefIndex].special = 0; + + // Spawn a battery, with the same level of charge. + HDMagAmmo.SpawnMag(self, "HDBattery", self.charges); + + // Spawn some smoke. + int smokeCount = random(1, 4); + float smokeVel = 20.0; + for(int k = 0; k < smokeCount; k++) { + A_SpawnItemEx( + "HDSmokeChunk", + 0.0, 0.0, 0.0, + frandom(-smokeVel, smokeVel), + frandom(-smokeVel, smokeVel), + frandom(-smokeVel, smokeVel)); + } + + // Spawn a bunch of sparks. + int sparkAmount = random(3,6); + for(int k = 0; k < sparkAmount; k++) { + SpawnSpark(); + } + + JumperCablesMapLoader loader = JumperCablesMapLoader.Get(); + loader.UnregisterCables(self); + + Destroy(); + } + + override bool OnGrab(Actor grabber) + { + DespawnToBattery(); + return false; + } + + void SpawnSpark() + { + float sparkSpeed = 5.0; + float sparkOffset = 2.0; + A_StartSound("misc/arccrackle", CHAN_AUTO); + A_SpawnParticle( + "white", + SPF_RELATIVE | SPF_FULLBRIGHT, + random(1, 10), // lifetime + frandom(1, 7), // size + 0, // angle + // offset... + frandom(-sparkOffset, sparkOffset), + frandom(-sparkOffset, sparkOffset), + frandom(-sparkOffset, sparkOffset), + // vel... + frandom(-sparkSpeed, sparkSpeed), + frandom(-sparkSpeed, sparkSpeed), + frandom(-sparkSpeed, sparkSpeed)); + } + + override void Tick() + { + if(frandom(0.0, 1.0) < 0.02) { + SpawnSpark(); + } + + // Despawn to battery if the sector gets re-destroyed. + if(level.lines[lineDefIndex].special == 0) + { + DespawnToBattery(); + } + } +} + +class JumperCablesUsable : HDWeapon +{ + int lastIndicatorStatus; + + default + { + +weapon.wimpy_weapon; + +inventory.invbar; + +hdweapon.droptranslation; + +hdweapon.fitsinbackpack; + hdweapon.barrelsize 0,0,0; + weapon.selectionorder 1014; + + scale 0.6; + inventory.icon "JMPKA0"; + inventory.pickupmessage "Picked up a wiring bypass kit."; + inventory.pickupsound "derp/crawl"; + translation 0; + tag "Wiring Bypass Kit"; + + hdweapon.refid HDLD_KIRI_JUMPERCABLES; + } + + override double WeaponBulk() + { + return 7; + } + + override bool AddSpareWeapon(actor newowner) + { + return AddSpareWeaponRegular(newowner); + } + + override hdweapon GetSpareWeapon(actor newowner,bool reverse,bool doselect) + { + return GetSpareWeaponRegular(newowner,reverse,doselect); + } + + override void DrawSightPicture( + HDStatusBar statusBar, + HDWeapon weapon, + HDPlayerPawn playerPawn, + bool sightbob, + Vector2 bob, + double fov, + bool scopeview, + Actor hpc, + String whichdot) + { + // Switch reticle colors depending on the LED status. + String filename = String.Format( + "graphics/jumpercables/jmpr_reticle%d.png", + lastIndicatorStatus + 1); + + statusBar.drawImage( + filename, + (0, 0) + bob, + statusBar.DI_SCREEN_CENTER | statusBar.DI_ITEM_TOP, + scale : (0.5, 0.5)); + } + + states + { + + spawn: + JMPP # 0 offset(0, -32); + JMPK A -1; + stop; + + select0: + JMPP A 1; + goto select0big; + + deselect0: + JMPP A 1; + goto deselect0big; + + // LCD overlay states. + ledd_left_indicator: + JMIL A 1 offset(0, -32); wait; + ledd_right_indicator: + JMIR A 1 offset(0, -32); wait; + + ready: + JMPP # 1 { + + if(PressingFire()) { + SetWeaponState("deploy"); + } + A_WeaponReady(WRF_NOFIRE | WRF_ALLOWUSER3); // USER3 = MagManager. + + // Line trace to see what we might be inspecting. + FLineTraceData linetraceData; + DoLineTrace(HDPlayerPawn(invoker.owner), linetraceData); + + // Overlay setup. + A_Overlay(355, "ledd_left_indicator"); + A_Overlay(356, "ledd_right_indicator"); + + // Update displays. + UpdateVisualsForLineTrace( + HDPlayerPawn(invoker.owner), + linetraceData); + } + goto readyend; + + readyend: + #### # 0 A_ReadyEnd(); + #### # 0 A_Jump(256,"ready"); + + deploy: + // Lower it down... + JMPP A 1 offset(0, 16); + JMPP A 1 offset(0, 32); + JMPP A 1 offset(0, 48); + JMPP A 1 offset(0, 64); + JMPP A 1 offset(0, 72); + JMPP A 1 offset(0, 96); + JMPP A 1 offset(0, 128); + + // Play some sounds. + JMPP A 0 A_JumpIf(!pressingfire(),"ready"); + JMPP A 4 A_StartSound("weapons/pismagclick",CHAN_WEAPON); + JMPP A 2 A_StartSound("derp/crawl",CHAN_WEAPON,CHANF_OVERLAP); + + // Actual cable attachment happens here. + JMPP A 1 { + AttachCables(HDPlayerPawn(invoker.owner)); + } + + // Raise it back up... + JMPP A 1 offset(0, 128); + JMPP A 1 offset(0, 96); + JMPP A 1 offset(0, 72); + JMPP A 1 offset(0, 64); + JMPP A 1 offset(0, 48); + JMPP A 1 offset(0, 32); + JMPP A 1 offset(0, 16); + JMPP A 1 offset(0, 0); + + JMPP A 1 { + A_WeaponReady(WRF_NOFIRE | WRF_ALLOWRELOAD | WRF_ALLOWUSER4); + } + + goto ready; + + user3: + #### # 0 A_MagManager("HDBattery"); + goto ready; + + } + + action void UpdateVisualsForLineTrace(HDPlayerPawn pawn, FLineTraceData linetraceData) + { + + Line hitLine = linetraceData.hitLine; + String particleColor = "darkred"; + Line brokenLine = LineTraceFindbrokenLine(linetraceData); + + // Set main frame (LEDs) based on raytrace status. + if(brokenLine) { + + // Found somethine we can fix! + particleColor = "green"; + player.getpsprite(PSP_WEAPON).frame = 1; + + } else { + + if(linetraceData.hitType == TRACE_HitNone) { + + // Didn't hit anything (yellow light). + player.getpsprite(PSP_WEAPON).frame = 0; + + } else{ + + // Hit something, but it's not broken (green light). + player.getpsprite(PSP_WEAPON).frame = 2; + + } + + } + + // Set display overlay frames. + + // Default to random numbers. + int frame_left = random(0, 15); + int frame_right = random(0, 15); + + Line lineForDisplay = brokenLine; + if(!lineForDisplay) { + lineForDisplay = hitLine; + } + if(lineForDisplay) { + JumperCablesMapLoader loader = JumperCablesMapLoader.Get(); + int originalSpecial = loader.originalLinedefSpecials2.Get(lineForDisplay.index()); + frame_right = originalSpecial % 16; + frame_left = originalSpecial / 16; + } + player.getpsprite(355).frame = frame_left; + player.getpsprite(356).frame = frame_right; + + // Play a sound if we just discovered a broken line. + if(invoker.lastIndicatorStatus != player.getpsprite(PSP_WEAPON).frame) { + if(invoker.lastIndicatorStatus != 1 && player.getpsprite(PSP_WEAPON).frame == 1) { + A_StartSound("herp/beep", CHAN_WEAPON); + } + } + + // Set indicator status fo the HUD. + invoker.lastIndicatorStatus = player.getpsprite(PSP_WEAPON).frame; + + // Debug particle display for the linetrace. + if(hd_debug > 1) { + if(linetraceData.hitType != TRACE_HitNone) { + Vector3 hitPos = linetraceData.hitLocation - Vec3Offset(0, 0, 0); + A_SpawnParticle( + particleColor, + 0, 10, 2, 0, + hitPos.x, + hitPos.y, + hitPos.z); + } + } + } + + action float Vec2Mag(Vector2 v) + { + return sqrt(v.x * v.x + v.y * v.y); + } + + action float GetDistanceToLine(Line testLine, Vector3 position) + { + Vector2 pos2d; + pos2d.x = position.x; + pos2d.y = position.y; + + Vector2 origin = testLine.v1.p; + + // Get the normalized direction from v1 to v2. + Vector2 direction = testLine.v2.p - origin; + float direction_magnitude = Vec2Mag(direction); + direction = direction / direction_magnitude; + + // Get the position relative to the origin. + pos2d -= origin; + + // Project pos2d onto direction, to get a position along the line. + double t = direction dot pos2d; + + // Clamp position along line to start/end. + if(t < 0.0) { + t = 0; + } + if(t > direction_magnitude) { + t = direction_magnitude; + } + + // Closest point on the line (as an offset from origin). + Vector2 position_on_line = direction * t; + + Vector2 delta_to_line = position_on_line - pos2d; + float final_distance = Vec2Mag(delta_to_line); + + return final_distance; + } + + action void DoLineTrace(HDPlayerPawn pawn, FLineTraceData linetraceData) + { + pawn.LineTrace( + pawn.angle, + 48, + pawn.pitch, + flags : TRF_THRUACTORS | TRF_ABSOFFSET, + offsetz : pawn.gunPos.z - 1, + offsetforward : pawn.gunPos.x, + offsetside : pawn.gunPos.y, + data : linetraceData); + } + + action Line LineTraceFindbrokenLine(FLineTraceData linetraceData) + { + JumperCablesMapLoader loader = JumperCablesMapLoader.Get(); + + // If we're placing this on a wall, then we'll just look at the wall's special. + if(linetraceData.hitType == TRACE_HitWall) { + + if(linetraceData.hitLine) { + + Line hitLine = linetraceData.hitLine; + + if(loader.originalLinedefSpecials2.CheckKey(hitLine.index())) { + + int originalSpecial = loader.originalLinedefSpecials2.Get(hitLine.index()); + int currentSpecial = hitLine.special; + + if(originalSpecial != currentSpecial) + { + return hitLine; + } + } + } + } + + // If we hit a sector *or* got close enough to another linedef + // attached to the sector that we're in, then let's find the + // closest linedef within range that we know is damaged. + if(linetraceData.hitType == TRACE_HitFloor || + linetraceData.hitType == TRACE_HitCeiling || + linetraceData.hitType == TRACE_HitWall) + { + Sector sec = linetraceData.hitSector; + Line closestLineInRange = null; + float closestLineDistance = jumperCablesFixRange; + + // Iterate through all linedefs connected to the sector. + for(int secLineIndex = 0; secLineIndex < sec.lines.size(); secLineIndex++) { + + Line secLine = sec.lines[secLineIndex]; + + // If this is currently special, we don't care about + // it (it's working fine, presumably). + if(secLine.special == 0) { + + // If this *used* to be special, we DO care about it! + if(loader.originalLinedefSpecials2.CheckKey(secLine.index())) { + + // Make sure it's actually changed. + int originalSpecial = loader.originalLinedefSpecials2.Get(secLine.index()); + int currentSpecial = secLine.special; + if(originalSpecial != currentSpecial) { + + // See if this is the closest one we've found so far. + float distanceToLine = GetDistanceToLine( + secLine, linetraceData.hitLocation); + if(distanceToLine <= closestLineDistance) { + closestLineInRange = secLine; + closestLineDistance = distanceToLine; + } + } + } + } + } + + // If we found something broken, then return the closest + // thing we found. + if(closestLineInRange) { + return closestLineInRange; + } + + } + + return null; + } + + action void AttachCables(HDPlayerPawn pawn) + { + // Do we have enough ammo? + HDMagAmmo batteryAmmo = HDMagAmmo(FindInventory("HDBattery")); + if(!batteryAmmo || batteryAmmo.amount < 1) { + invoker.owner.A_Log("You need a battery to use this."); + return; + } + + JumperCablesMapLoader loader = JumperCablesMapLoader.Get(); + FLineTraceData linetraceData; + DoLineTrace(pawn, linetraceData); + + // Are we even close enough to a line? + Line brokenLine = LineTraceFindbrokenLine(linetraceData); + if(!brokenLine) { + invoker.owner.A_Log("Not close enough to repair."); + return; + } + + if(!loader.originalLinedefSpecials2.CheckKey(brokenLine.index())) { + invoker.owner.A_Log("No mechanism present to repair."); + return; + } + + // Check to see if it's something that actually needs fixing. + int originalSpecial = loader.originalLinedefSpecials2.Get(brokenLine.index()); + int currentSpecial = brokenLine.special; + if(originalSpecial == currentSpecial) { + invoker.owner.A_Log("This is already functioning as normal."); + return; + } + + // Remove battery from inventory, but make sure we're actually + // getting a charged one. + int batteryCharges = batteryAmmo.TakeMag(true); + if(batteryCharges < 1) { + invoker.owner.A_Log("No charged batteries available to use."); + batteryAmmo.AddAMag(batteryCharges); // Just give it back. + return; + } + + // Actually spawn the deployed item. + JumperCablesDeployed deployed = JumperCablesDeployed( + Spawn( + "JumperCablesDeployed", + linetraceData.hitLocation - linetraceData.hitDir * 4)); + + deployed.lineDefIndex = brokenLine.index(); + deployed.bNoGravity = true; + deployed.charges = batteryCharges; + + // Use a different kind of flat sprite and angle depending on + // if we're attaching to wall or floor/ceiling. + if(linetraceData.hitType == TRACE_HitFloor || linetraceData.hitType == TRACE_HitCeiling) { + deployed.SetFlatSprite(invoker.owner.angle); + } else { + Vector2 lineDir = linetraceData.hitLine.v2.p - linetraceData.hitLine.v1.p; + deployed.SetWallSprite(lineDir); + } + + // Restore the damn line special already. + brokenLine.special = originalSpecial; + } + + override void DrawHUDStuff(HDStatusBar statusBar, HDWeapon weapon, HDPlayerPawn pawn) + { + // Copied and modified from ThunderBuster display. + if(statusBar.hudlevel == 1) { + statusBar.DrawBattery( + -54, -4, + statusBar.DI_SCREEN_CENTER_BOTTOM, + reloadorder : true); + statusBar.DrawNum( + pawn.CountInv("HDBattery"), + -46, -8, + statusBar.DI_SCREEN_CENTER_BOTTOM); + } + } + + override String GetHelpText() + { + return WEPHELP_FIRE.." Deploy\n"; + } +} + diff --git a/zscript/snektech.zs b/zscript/snektech.zs index 8fcf763..ffba9a7 100644 --- a/zscript/snektech.zs +++ b/zscript/snektech.zs @@ -1,6 +1,7 @@ enum SnekTechSpawnFlags { - SNEKTECH_GRETCHENCOUNTER = 0 + SNEKTECH_GRETCHENCOUNTER = 0, + SNEKTECH_JUMPERCABLES = 1 } class SnekTechEventHandler : EventHandler @@ -56,7 +57,15 @@ class SnekTechEventHandler : EventHandler } // Delete disabled items from backpacks that just spawned. - DoSnekTechBackpackSpawnCheck(e.Thing, SNEKTECH_GRETCHENCOUNTER, "GretchenCounter"); + DoSnekTechBackpackSpawnCheck( + e.Thing, + SNEKTECH_GRETCHENCOUNTER, + "GretchenCounter"); + + DoSnekTechBackpackSpawnCheck( + e.Thing, + SNEKTECH_JUMPERCABLES, + "JumperCablesUsable"); } override void CheckReplacement(ReplaceEvent e) @@ -69,7 +78,15 @@ class SnekTechEventHandler : EventHandler return; } - DoSnekTechReplacement(SNEKTECH_GRETCHENCOUNTER, "Stimpack", "GretchenCounter", 12, e); + DoSnekTechReplacement( + SNEKTECH_GRETCHENCOUNTER, + "Stimpack", "GretchenCounter", + 12, e); + + DoSnekTechReplacement( + SNEKTECH_JUMPERCABLES, + "Allmap", "JumperCablesUsable", + 256, e); } }