Making room for other items.
This commit is contained in:
parent
d484cca3be
commit
8bd41d7969
@ -1,5 +1,5 @@
|
|||||||
gameinfo
|
gameinfo
|
||||||
{
|
{
|
||||||
AddEventHandlers = "GretchenCounterEventHandler"
|
AddEventHandlers = "SnekTechEventHandler"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
491
zscript.zs
491
zscript.zs
@ -1,491 +1,4 @@
|
|||||||
version "4.10"
|
version "4.10"
|
||||||
|
|
||||||
enum SnekTechSpawnFlags
|
#include "zscript/snektech.zs"
|
||||||
{
|
#include "zscript/gretchencounter.zs"
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
433
zscript/gretchencounter.zs
Normal file
433
zscript/gretchencounter.zs
Normal file
@ -0,0 +1,433 @@
|
|||||||
|
#include "zscript/snektech.zs"
|
||||||
|
|
||||||
|
const HDLD_KIRI_GRETCHENCOUNTER = "kgc";
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
75
zscript/snektech.zs
Normal file
75
zscript/snektech.zs
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
enum SnekTechSpawnFlags
|
||||||
|
{
|
||||||
|
SNEKTECH_GRETCHENCOUNTER = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
class SnekTechEventHandler : EventHandler
|
||||||
|
{
|
||||||
|
bool GetItemEnabled(int item)
|
||||||
|
{
|
||||||
|
int spawnFlags = CVar.GetCVar("snektech_spawnflags").GetInt();
|
||||||
|
if(spawnFlags & (1 << item)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DoSnekTechBackpackSpawnCheck(
|
||||||
|
Actor maybePack,
|
||||||
|
int itemFlagIndex,
|
||||||
|
String itemClass)
|
||||||
|
{
|
||||||
|
HDBackpack pack = HDBackpack(maybePack);
|
||||||
|
if(pack && !pack.owner) {
|
||||||
|
if(!GetItemEnabled(itemFlagIndex)) {
|
||||||
|
pack.storage.DestroyItem(itemClass);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DoSnekTechReplacement(
|
||||||
|
int itemFlagIndex,
|
||||||
|
class<Actor> Replacee,
|
||||||
|
class<Actor> Replacement,
|
||||||
|
int chance,
|
||||||
|
ReplaceEvent e)
|
||||||
|
{
|
||||||
|
if(GetItemEnabled(itemFlagIndex)) {
|
||||||
|
if(e.Replacee == Replacee) {
|
||||||
|
if(random() < chance) {
|
||||||
|
e.Replacement = Replacement;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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.
|
||||||
|
DoSnekTechBackpackSpawnCheck(e.Thing, SNEKTECH_GRETCHENCOUNTER, "GretchenCounter");
|
||||||
|
}
|
||||||
|
|
||||||
|
override void CheckReplacement(ReplaceEvent e)
|
||||||
|
{
|
||||||
|
if(!e.Replacement) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(e.isFinal) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
DoSnekTechReplacement(SNEKTECH_GRETCHENCOUNTER, "Stimpack", "GretchenCounter", 12, e);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user