commit d484cca3be267bcadd355c7144f420879a0973be Author: Kiri Date: Sat Sep 2 18:20:13 2023 -0700 Adding frag counter first. diff --git a/cvarinfo.txt b/cvarinfo.txt new file mode 100644 index 0000000..f17899a --- /dev/null +++ b/cvarinfo.txt @@ -0,0 +1 @@ +server int snektech_spawnflags = 1; diff --git a/gldefs.txt b/gldefs.txt new file mode 100644 index 0000000..e4e213f --- /dev/null +++ b/gldefs.txt @@ -0,0 +1,35 @@ +brightmap sprite kgcma0 +{ + map "sprites/bright_kgcma0.png" + disablefullbright +} + +brightmap sprite kgcmb0 +{ + map "sprites/bright_kgcmb0.png" + disablefullbright +} + +brightmap sprite kgcna0 +{ + map "sprites/bright_kgcma0.png" + disablefullbright +} + +brightmap sprite kgcnb0 +{ + map "sprites/bright_kgcmb0.png" + disablefullbright +} + +brightmap sprite kgcpa0 +{ + map "sprites/bright_kgcpa0.png" + disablefullbright +} + +brightmap sprite kgcpb0 +{ + map "sprites/bright_kgcpb0.png" + disablefullbright +} diff --git a/mapinfo.txt b/mapinfo.txt new file mode 100644 index 0000000..59650d6 --- /dev/null +++ b/mapinfo.txt @@ -0,0 +1,5 @@ +gameinfo +{ + AddEventHandlers = "GretchenCounterEventHandler" +} + diff --git a/menudef.txt b/menudef.txt new file mode 100644 index 0000000..b1551b2 --- /dev/null +++ b/menudef.txt @@ -0,0 +1,12 @@ +AddOptionMenu "OptionsMenu" +{ + Submenu "Snektech Discount Party Pack", "SnekTechMenu" +} + +OptionMenu "SnekTechMenu" +{ + Title "SnekTech Discount Party Pack" + StaticText "----- Item Spawns -----", "Teal" + FlagOption "Gretchen Counter", "snektech_spawnflags", "YesNo", 0 +} + diff --git a/sndinfo.txt b/sndinfo.txt new file mode 100644 index 0000000..7fdcf02 --- /dev/null +++ b/sndinfo.txt @@ -0,0 +1,3 @@ +kiri/gretchencounter_click "sounds/kirigretchencounter_click.ogg" +kiri/gretchencounter_blip "sounds/kirigretchencounter_blip.ogg" +kiri/gretchencounter_onoff "sounds/kirigretchencounter_onoff.ogg" diff --git a/sounds/kirigretchencounter_blip.ogg b/sounds/kirigretchencounter_blip.ogg new file mode 100644 index 0000000..5478699 Binary files /dev/null and b/sounds/kirigretchencounter_blip.ogg differ diff --git a/sounds/kirigretchencounter_click.ogg b/sounds/kirigretchencounter_click.ogg new file mode 100644 index 0000000..b5cff5a Binary files /dev/null and b/sounds/kirigretchencounter_click.ogg differ diff --git a/sounds/kirigretchencounter_onoff.ogg b/sounds/kirigretchencounter_onoff.ogg new file mode 100644 index 0000000..04d7ad4 Binary files /dev/null and b/sounds/kirigretchencounter_onoff.ogg differ diff --git a/source_data/Makefile b/source_data/Makefile new file mode 100644 index 0000000..6cd6a97 --- /dev/null +++ b/source_data/Makefile @@ -0,0 +1,105 @@ +all : \ + ../sprites/kgcmb0.png \ + ../sprites/kgcma0.png \ + ../sprites/kgcmc0.png \ + ../sprites/kgcna0.png \ + ../sprites/kgcnb0.png \ + ../sprites/bright_kgcma0.png \ + ../sprites/bright_kgcmb0.png \ + ../sounds/kirigretchencounter_click.ogg \ + ../sounds/kirigretchencounter_blip.ogg \ + ../sounds/kirigretchencounter_onoff.ogg \ + ../sprites/kgcpa0.png \ + ../sprites/kgcpb0.png \ + ../sprites/bright_kgcpa0.png \ + ../sprites/bright_kgcpb0.png \ + ../sprites/bright_kgcmc0.png + +# Base frames +../sprites/kgcma0.png : gretchencounter_weaponsprite.aseprite + aseprite $^ \ + -b \ + --ignore-layer "brightmap" \ + --frame-range 0,0 --save-as $@ + +../sprites/kgcmb0.png : gretchencounter_weaponsprite.aseprite + aseprite $^ \ + -b \ + --ignore-layer "brightmap" \ + --frame-range 1,1 --save-as $@ + +../sprites/kgcmc0.png : gretchencounter_weaponsprite.aseprite + aseprite $^ \ + -b \ + --ignore-layer "brightmap" \ + --frame-range 2,2 --save-as $@ + +# Brightmaps +../sprites/bright_kgcma0.png : gretchencounter_weaponsprite.aseprite + aseprite $^ \ + -b \ + --layer "brightmap" \ + --frame-range 0,0 --save-as $@ + +../sprites/bright_kgcmb0.png : gretchencounter_weaponsprite.aseprite + aseprite $^ \ + -b \ + --layer "brightmap" \ + --frame-range 1,1 --save-as $@ + +../sprites/bright_kgcmc0.png : gretchencounter_weaponsprite.aseprite + aseprite $^ \ + -b \ + --layer "brightmap" \ + --frame-range 2,2 --save-as $@ + +# Needle +../sprites/kgcna0.png : gretchencounter_weaponsprite.aseprite + aseprite $^ \ + -b \ + --layer "needle" \ + --frame-range 0,0 --save-as $@ + +../sprites/kgcnb0.png : gretchencounter_weaponsprite.aseprite + aseprite $^ \ + -b \ + --layer "needle" \ + --frame-range 1,1 --save-as $@ + +# Pickup sprite +../sprites/kgcpa0.png : gretchencounter_pickupsprite.aseprite + aseprite $^ \ + -b \ + --ignore-layer "brightmap" \ + --frame-range 0,0 --save-as $@ + +../sprites/kgcpb0.png : gretchencounter_pickupsprite.aseprite + aseprite $^ \ + -b \ + --ignore-layer "brightmap" \ + --frame-range 1,1 --save-as $@ + +../sprites/bright_kgcpa0.png : gretchencounter_pickupsprite.aseprite + aseprite $^ \ + -b \ + --layer "brightmap" \ + --frame-range 0,0 --save-as $@ + +../sprites/bright_kgcpb0.png : gretchencounter_pickupsprite.aseprite + aseprite $^ \ + -b \ + --layer "brightmap" \ + --frame-range 1,1 --save-as $@ + + + + +# Sounds +../sounds/kirigretchencounter_click.ogg : kirigretchencounter_click.wav + ffmpeg -i $^ "-filter:a" "volume=1.0" $@ + +../sounds/kirigretchencounter_blip.ogg : kirigretchencounter_blip.wav + ffmpeg -i $^ "-filter:a" "volume=1.0" $@ + +../sounds/kirigretchencounter_onoff.ogg : on_off_switch.wav + ffmpeg -i $^ "-filter:a" "volume=1.0" $@ diff --git a/source_data/gretchencounter_pickupsprite.aseprite b/source_data/gretchencounter_pickupsprite.aseprite new file mode 100644 index 0000000..2cd5e33 Binary files /dev/null and b/source_data/gretchencounter_pickupsprite.aseprite differ diff --git a/source_data/gretchencounter_weaponsprite.aseprite b/source_data/gretchencounter_weaponsprite.aseprite new file mode 100644 index 0000000..c6a047f Binary files /dev/null and b/source_data/gretchencounter_weaponsprite.aseprite differ diff --git a/source_data/kirigretchencounter_blip.wav b/source_data/kirigretchencounter_blip.wav new file mode 100644 index 0000000..c814866 Binary files /dev/null and b/source_data/kirigretchencounter_blip.wav differ diff --git a/source_data/kirigretchencounter_click.wav b/source_data/kirigretchencounter_click.wav new file mode 100644 index 0000000..b2d1cbf Binary files /dev/null and b/source_data/kirigretchencounter_click.wav differ diff --git a/source_data/on_off_switch.aup3 b/source_data/on_off_switch.aup3 new file mode 100644 index 0000000..8005d4b Binary files /dev/null and b/source_data/on_off_switch.aup3 differ diff --git a/source_data/on_off_switch.wav b/source_data/on_off_switch.wav new file mode 100644 index 0000000..9d2a8d0 Binary files /dev/null and b/source_data/on_off_switch.wav differ diff --git a/sprites/bright_kgcma0.png b/sprites/bright_kgcma0.png new file mode 100644 index 0000000..ea27c66 Binary files /dev/null and b/sprites/bright_kgcma0.png differ diff --git a/sprites/bright_kgcmb0.png b/sprites/bright_kgcmb0.png new file mode 100644 index 0000000..698b0f3 Binary files /dev/null and b/sprites/bright_kgcmb0.png differ diff --git a/sprites/bright_kgcmc0.png b/sprites/bright_kgcmc0.png new file mode 100644 index 0000000..ea27c66 Binary files /dev/null and b/sprites/bright_kgcmc0.png differ diff --git a/sprites/bright_kgcpa0.png b/sprites/bright_kgcpa0.png new file mode 100644 index 0000000..1edd33f Binary files /dev/null and b/sprites/bright_kgcpa0.png differ diff --git a/sprites/bright_kgcpb0.png b/sprites/bright_kgcpb0.png new file mode 100644 index 0000000..0acea52 Binary files /dev/null and b/sprites/bright_kgcpb0.png differ diff --git a/sprites/kgcma0.png b/sprites/kgcma0.png new file mode 100644 index 0000000..a3f26e9 Binary files /dev/null and b/sprites/kgcma0.png differ diff --git a/sprites/kgcmb0.png b/sprites/kgcmb0.png new file mode 100644 index 0000000..a0a837a Binary files /dev/null and b/sprites/kgcmb0.png differ diff --git a/sprites/kgcmc0.png b/sprites/kgcmc0.png new file mode 100644 index 0000000..a0a837a Binary files /dev/null and b/sprites/kgcmc0.png differ diff --git a/sprites/kgcna0.png b/sprites/kgcna0.png new file mode 100644 index 0000000..319e80a Binary files /dev/null and b/sprites/kgcna0.png differ diff --git a/sprites/kgcnb0.png b/sprites/kgcnb0.png new file mode 100644 index 0000000..319e80a Binary files /dev/null and b/sprites/kgcnb0.png differ diff --git a/sprites/kgcpa0.png b/sprites/kgcpa0.png new file mode 100644 index 0000000..f7b70d1 Binary files /dev/null and b/sprites/kgcpa0.png differ diff --git a/sprites/kgcpb0.png b/sprites/kgcpb0.png new file mode 100644 index 0000000..f7b70d1 Binary files /dev/null and b/sprites/kgcpb0.png differ diff --git a/textures.txt b/textures.txt new file mode 100644 index 0000000..479051e --- /dev/null +++ b/textures.txt @@ -0,0 +1,9 @@ +sprite KGCPA0, 32, 32 { + offset 16, 32 + patch KGCPA0,0,0 { } +} + +sprite KGCPB0, 32, 32 { + offset 16, 32 + patch KGCPB0,0,0 { } +} diff --git a/zscript.zs b/zscript.zs new file mode 100644 index 0000000..076b5d8 --- /dev/null +++ b/zscript.zs @@ -0,0 +1,491 @@ +version "4.10" + +enum SnekTechSpawnFlags +{ + SNEKTECH_GRETCHENCOUNTER = 0 +} + +const HDLD_KIRI_GRETCHENCOUNTER = "kgc"; + +class GretchenCounterEventHandler : EventHandler +{ + bool GetItemEnabled(int item) + { + int spawnFlags = CVar.GetCVar("snektech_spawnflags").GetInt(); + if(spawnFlags & (1 << item)) { + return true; + } + return false; + } + + override void WorldThingSpawned(WorldEvent e) + { + if(!e.Thing) { + return; + } + + // Disable drop useless ammo for batteries. + HDBattery bat = HDBattery(e.Thing); + if(bat) { + bat.ItemsThatUseThis.Push("GretchenCounter"); + } + + // Delete disabled items from backpacks that just spawned. + HDBackpack pack = HDBackpack(e.Thing); + if(pack && !pack.owner) { + if(!GetItemEnabled(SNEKTECH_GRETCHENCOUNTER)) { + pack.storage.DestroyItem("GretchenCounter"); + } + } + } + + override void CheckReplacement(ReplaceEvent e) + { + if(!e.Replacement) { + return; + } + + if(e.isFinal) { + return; + } + + if(GetItemEnabled(SNEKTECH_GRETCHENCOUNTER)) { + if(e.Replacee == "Stimpack") { + if(random() < 12) { + e.Replacement = "GretchenCounter"; + } + } + } + } + +} + +enum GretchenCounterStatus +{ + KGC_BATTERY=0, + KGC_ACTIVE=1 +} + +class GretchenCounter : HDWeapon +{ + default + { + +weapon.wimpy_weapon; + +inventory.invbar; + +hdweapon.droptranslation; + +hdweapon.fitsinbackpack; + hdweapon.barrelsize 0,0,0; + weapon.selectionorder 1014; + + scale 0.6; + inventory.icon "KGCPA0"; + inventory.pickupmessage "Picked up a Gretchen Counter."; + inventory.pickupsound "derp/crawl"; + translation 0; + tag "Gretchen Counter"; + + hdweapon.refid HDLD_KIRI_GRETCHENCOUNTER; + } + + float lastReading; + float angularVelocity; + float needlePosition; + int framesSinceLastBeep; + int lastBatteryCheckFrame; + + override bool AddSpareWeapon(actor newowner) + { + return AddSpareWeaponRegular(newowner); + } + + override HDWeapon GetSpareWeapon(actor newowner, bool reverse, bool doselect) + { + return GetSpareWeaponRegular(newowner, reverse, doselect); + } + + int hash(int x) + { + x = ((x >> 16) ^ x) * 0x45d9f3b; + x = ((x >> 16) ^ x) * 0x45d9f3b; + x = (x >> 16) ^ x; + return x; + } + + bool HasBatteryCharge() + { + int bat = weaponstatus[KGC_BATTERY]; + if(bat > 0) { + + int timeHash = hash(level.time / 10); + if((timeHash % 5) < bat) { + return true; + } + } + return false; + } + + void TickBattery() + { + if(weaponstatus[KGC_ACTIVE] && + weaponstatus[KGC_BATTERY] > 0) + { + // Discharge rate: 1/1000 chance per tick. + int r = random(0, 4000); + if(r < 2) { + weaponstatus[KGC_BATTERY] -= 1; + } + } + } + + states + { + spawn: + KGCP # 1 { frame = invoker.GetIsActive(); } + loop; + + // Needle overlay states. + needle_indicator: + KGCN # 1; wait; + + select0: + KGCM # 1 { + updateOverlay(); + } + goto select0big; + + deselect0: + KGCM # 1 { + updateOverlay(); + } + goto deselect0big; + + user3: + #### A 0 A_MagManager("HDBattery"); + goto ready; + + + unload: + KGCM # 1 offset(0, 20) { updateOverlay(); } + KGCM # 1 offset(0, 40) { updateOverlay(); } + KGCM # 1 offset(0, 55) { updateOverlay(); } + + KGCM # 10 { + if(invoker.weaponstatus[KGC_BATTERY] != -1) { + A_StartSound("weapons/pocket", 9); + HDMagAmmo.GiveMag(self, "HDBattery", invoker.weaponstatus[KGC_BATTERY]); + invoker.weaponstatus[KGC_BATTERY] = -1; + } + } + + KGCM # 1 offset(0, 55) { updateOverlay(); } + KGCM # 1 offset(0, 40) { updateOverlay(); } + KGCM # 1 offset(0, 20) { updateOverlay(); } + KGCM # 1 offset(0, 0) { updateOverlay(); } + goto ready; + + reload: + KGCM # 1 offset(0, 20) { updateOverlay(); } + KGCM # 1 offset(0, 40) { updateOverlay(); } + KGCM # 1 offset(0, 55) { updateOverlay(); } + + KGCM # 10 { + if(CountInv("HDBattery")) { + + // Unload existing battery. + if(invoker.weaponstatus[KGC_BATTERY] != -1) { + A_StartSound("weapons/pocket", 9); + HDMagAmmo.GiveMag(self, "HDBattery", invoker.weaponstatus[KGC_BATTERY]); + invoker.weaponstatus[KGC_BATTERY] = -1; + } + + // Load new mag. + A_StartSound("weapons/plasload", 8); + HDMagAmmo magAmmo = HDMagAmmo( + FindInventory("HDBattery")); + if(magAmmo) { + invoker.weaponstatus[KGC_BATTERY] = magAmmo.TakeMag(true); + } + } + } + + KGCM # 1 offset(0, 55) { updateOverlay(); } + KGCM # 1 offset(0, 40) { updateOverlay(); } + KGCM # 1 offset(0, 20) { updateOverlay(); } + KGCM # 1 offset(0, 0) { updateOverlay(); } + goto ready; + + ready: + KGCM B 1 { + A_Overlay(355, "needle_indicator"); + A_OverlayPivotAlign(355, PSPA_CENTER, PSPA_BOTTOM); + // invoker.UpdateDisplay(); + updateOverlay(); + + // USER3 = MagManager. + // USER4 = Unload. + A_WeaponReady(WRF_ALLOWUSER3 | WRF_ALLOWUSER4 | WRF_ALLOWRELOAD); + } + + goto readyend; + + fire: + KGCM # 1 offset(0, 20) { updateOverlay(); } + KGCM # 1 offset(0, 40) { updateOverlay(); } + KGCM # 1 offset(0, 55) { updateOverlay(); } + + KGCM # 1 { + invoker.weaponstatus[KGC_ACTIVE] = + !invoker.weaponstatus[KGC_ACTIVE]; + A_PlaySound("kiri/gretchencounter_onoff"); + updateOverlay(); + } + + KGCM # 1 offset(0, 55) { updateOverlay(); } + KGCM # 1 offset(0, 40) { updateOverlay(); } + KGCM # 1 offset(0, 20) { updateOverlay(); } + KGCM # 1 offset(0, 0) { updateOverlay(); } + goto waiting; + + waiting: + KGCM # 1 { updateOverlay(); } + KGCM # 1 { updateOverlay(); } + KGCM # 1 { updateOverlay(); } + KGCM # 1 { updateOverlay(); } + KGCM # 1 { updateOverlay(); } + KGCM # 1 A_Refire("waiting"); + goto ready; + + readyend: + #### # 0 A_ReadyEnd(); + #### # 0 A_Jump(256,"ready"); + } + + action void updateOverlay() + { + float angle_min = -45.0; + float angle_max = 45.0; + A_OverlayRotate(355, + angle_min + (angle_max - angle_min) * (1.0 - invoker.needlePosition)); + + if(invoker.weaponstatus[KGC_ACTIVE]) { + if(invoker.HasBatteryCharge()) { + player.getpsprite(PSP_WEAPON).frame = 1; + } else { + player.getpsprite(PSP_WEAPON).frame = 2; + } + } else { + player.getpsprite(PSP_WEAPON).frame = 0; + } + + player.getpsprite(355).frame = int(invoker.GetIsActive()); + } + + float GetReadingForType(String type_name, float distance_scale) + { + ThinkerIterator iter = ThinkerIterator.Create(type_name); + Actor mo; + float totalReading = 0.0; + + Actor referenceActor = owner; + if(!referenceActor) { + referenceActor = self; + } + + while(mo = Actor(iter.Next())) + { + if(mo.health <= 0) { + continue; + } + + float dist = referenceActor.Distance3D(mo); + + // Convert to "meters" (with a minimum). + if(dist < 32) { + dist = 32; + } + + // Scale distance. + dist *= distance_scale; + + // Apply inverse-square falloff. + totalReading += 1.0 / (dist * dist); + } + + return totalReading; + } + + override void Tick() + { + super.Tick(); + UpdateDisplay(); + TickBattery(); + } + + override void DrawHUDStuff( + HDStatusBar statusBar, HDWeapon weapon, + HDPlayerPawn pawn) + { + 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); + } + + int bat = weapon.weaponstatus[KGC_BATTERY]; + if(bat > 0) { + + // Draw battery bar. + statusbar.drawwepnum(bat, 20); + + } else if(bat > -1) { + + // No battery. + statusBar.drawstring( + statusBar.mamountfont, "00000", + (-16,-9), + statusBar.DI_TEXT_ALIGN_RIGHT | + statusBar.DI_TRANSLATABLE | + statusBar.DI_SCREEN_CENTER_BOTTOM, + Font.CR_DARKGRAY); + } + + } + + bool GetIsActive() + { + return weaponstatus[KGC_ACTIVE] && + HasBatteryCharge(); + } + + override void InitializeWepStats(bool idfa) + { + weaponstatus[KGC_BATTERY] = 20; + weaponstatus[KGC_ACTIVE] = 0; + super.InitializeWepStats(idfa); + } + + override double WeaponBulk() + { + int battery_weight = 0; + if(weaponstatus[KGC_BATTERY] != -1) { + // Battery bulk = 18, but inside this combines with its + // bulk (takes up less room). + battery_weight = 10; + } + + // This item's bulk is 20. Battery adds to that. + return battery_weight + 20; + } + + void UpdateDisplay() + { + Actor referenceActor = owner; + if(!referenceActor) { + 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; + // } + + float totalReading = 0.0; + if(GetIsActive()) { + totalReading = + GetReadingForType("BFGNecroShard", 1.0) + + GetReadingForType("HDBarrel", 2.0); + } + + // lastReading = totalReading * 0.01 + lastReading * 0.99; + + float pct_reading = lastReading * 2000.0; + + lastReading = totalReading; + + 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)); + + + angularvelocity += pct_reading - needlePosition; + angularvelocity *= 0.97; + + 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); + + + framesSinceLastBeep++; + // if(GetIsActive()) + { + if(!wasNeedleAtMax || framesSinceLastBeep > 15) { + if(needlePosition >= 0.9) { + referenceActor.A_StartSound("kiri/gretchencounter_blip"); + framesSinceLastBeep = 0; + } + } + } + } + + override string GetHelpText() + { + return "" + ..WEPHELP_FIRE.." Toggle on/off\n" + ..WEPHELP_RELOAD.." Reload battery\n" + ..WEPHELP_UNLOAD.." Remove battery\n" + ..WEPHELP_MAGMANAGER; + } +} +