Compare commits

..

14 Commits

Author SHA1 Message Date
b8b8705e38 Fixed Cacodemon name gain. 2024-11-09 08:24:46 -08:00
b2d0b6e1df Updated monster class names in the Caco plushie in response to some deprecation warnings. Added Bucky to the random name list. 2024-06-29 09:04:41 -07:00
emmie
e82101d9cb spraycan: actually explain SpawnDecal arg0 thing 2023-09-13 18:26:54 -07:00
c453013abf Added reverse cycling for the spray pattern selection. Also shows list index now. 2023-09-12 20:44:37 -07:00
364fb7e7ab Added KiriInstantFade back in, as essentaially a no-op, because a bunch of user-made sprays already refer to it. Removed KiriInstantFade from the example sprays. 2023-09-12 20:16:04 -07:00
emmie
56a46d0790 spraycan: use permanent decals
instead of using auto decals, letting them time out and just Not
replacing them when they're meant to be gone, this spawns a permanent
decal (not affected by decal limit) and explicitly deletes it when
necessary.
as a consequence of this, spraying more than 11 decals Immediately
removes the oldest spray.

Addresses issue #1
2023-09-11 20:47:55 -07:00
emmie
f4bf7a793e spraycan: fix cvar not being updated properly
GetCVar returns a per-player copy of the requested cvar, which is only
used to have separate values for each player - changes are propagated To
it, but not From it.
writing to this cvar is only useful if you know what the actual new
value is going to be & want the cvar to update Immediately.
(in this case, the cvar needs to be updated before A_SetHelpText so the
 displayed spray name is correct)

FindCVar returns the actual cvar for the local player. changes to this
cvar Are propagated to other clients.
2023-09-11 20:47:55 -07:00
emmie
333c40e46a silence implicit float->int conversion warnings 2023-09-11 20:47:55 -07:00
emmie
829c9c1242 fix dropped item sprites clipping into ground
fixes sprites being offset into the floor with automatic sprite clipping
adjustment disabled
2023-09-11 20:47:55 -07:00
b750dd6663 Set max sprays to a CVar. 2023-09-10 19:51:53 -07:00
f02ef045c1 Reduced spawn rate for frag counter. 2023-09-09 21:10:00 -07:00
74dfb16dff Doubled number of sprays that persist per player. Added example spray mod. 2023-09-09 18:03:56 -07:00
fe249bb6eb Made frag counter batteries last longer. 2023-09-09 17:49:43 -07:00
da6670956d Documented the spray cans, barely. 2023-09-09 16:54:49 -07:00
12 changed files with 207 additions and 101 deletions

View File

@ -131,3 +131,28 @@ Caution: May bite.
Loadout code: kac Loadout code: kac
## Spraypaint Cans
![Spray can sprite](sprites/spraycan/ksprb0.png)
It's just spraypaint.
Use it to cause property damage to the tyrant. Be creative while doing
so!
### How to use
Loadout code: ksp
Shake before attempting to spray.
Use firemode to select spray pattern.
Use the CVar `snektech_spraypattern` to directly set a spray pattern
name.
Use the CVar `snektech_maxspraysperplayer` to set the number of images
each player can spray before old ones are no longer refreshed
(non-refreshed ones will eventually disappear).

View File

@ -1,2 +1,3 @@
server int snektech_spawnflags = 11; server int snektech_spawnflags = 11;
server int snektech_maxspraysperplayer = 10;
user string snektech_spraypattern = "SnekSpray_TransPride"; user string snektech_spraypattern = "SnekSpray_TransPride";

View File

@ -1,20 +1,25 @@
fader KiriInstantFade stretcher KiriInstantFade
{ {
DecayStart 60.0 // You don't need this anymore! It's just here because a bunch of
DecayTime 0.0 // sprays were already made that use it!
// These numbers are designed to do nothing, and wait a long time
// before doing it. It's a no-op.
GoalX 1.0
GoalY 1.0
StretchStart 9999999.0
StretchTime 9999999.0
} }
decal KiriTestDecal decal KiriTestDecal
{ {
pic KSPYA0 pic KSPYA0
animator KiriInstantFade
randomflipx randomflipx
} }
decal SnekSpray_TransPride decal SnekSpray_TransPride
{ {
pic KSPYA0 pic KSPYA0
animator KiriInstantFade
randomflipx randomflipx
translucent 0.8 translucent 0.8
} }
@ -22,7 +27,6 @@ decal SnekSpray_TransPride
decal SnekSpray_LesbianPride decal SnekSpray_LesbianPride
{ {
pic KSPYB0 pic KSPYB0
animator KiriInstantFade
randomflipx randomflipx
translucent 0.8 translucent 0.8
} }
@ -30,7 +34,6 @@ decal SnekSpray_LesbianPride
decal SnekSpray_NBPride decal SnekSpray_NBPride
{ {
pic KSPYC0 pic KSPYC0
animator KiriInstantFade
randomflipx randomflipx
translucent 0.8 translucent 0.8
} }
@ -38,7 +41,6 @@ decal SnekSpray_NBPride
decal SnekSpray_AcePride decal SnekSpray_AcePride
{ {
pic KSPYD0 pic KSPYD0
animator KiriInstantFade
randomflipx randomflipx
translucent 0.8 translucent 0.8
} }
@ -46,34 +48,29 @@ decal SnekSpray_AcePride
decal SnekSpray_ProgressPride decal SnekSpray_ProgressPride
{ {
pic KSPYE0 pic KSPYE0
animator KiriInstantFade
translucent 0.8 translucent 0.8
} }
decal SnekSpray_DemiPride decal SnekSpray_DemiPride
{ {
pic KSPYF0 pic KSPYF0
animator KiriInstantFade
translucent 0.8 translucent 0.8
} }
decal SnekSpray_PanPride decal SnekSpray_PanPride
{ {
pic KSPYG0 pic KSPYG0
animator KiriInstantFade
translucent 0.8 translucent 0.8
} }
decal SnekSpray_SwitchPride decal SnekSpray_SwitchPride
{ {
pic KSPYH0 pic KSPYH0
animator KiriInstantFade
} }
decal SnekSpray_BiPride decal SnekSpray_BiPride
{ {
pic KSPYI0 pic KSPYI0
animator KiriInstantFade
translucent 0.8 translucent 0.8
randomflipx randomflipx
} }
@ -81,7 +78,6 @@ decal SnekSpray_BiPride
decal SnekSpray_GayPride decal SnekSpray_GayPride
{ {
pic KSPYJ0 pic KSPYJ0
animator KiriInstantFade
translucent 0.8 translucent 0.8
randomflipx randomflipx
} }

View File

@ -0,0 +1,6 @@
decal SnekSpray_Example
{
pic KSPEA0
translucent 0.8
randomflipx
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

View File

@ -0,0 +1,7 @@
Sprite "KSPEA0", 250, 150
{
XScale 2
YScale 2
Offset 125, 75
Patch "sprites/sprays/example_spray.png", 0, 0
}

View File

@ -0,0 +1,9 @@
class SnekSpray_Example : SnekTechSprayerPattern
{
default
{
SnekTechSprayerPattern.decalName "SnekSpray_Example";
}
}

View File

@ -35,7 +35,7 @@ sprite JMPRD0, 49, 43 {
} }
sprite JMPKA0, 48, 32 { sprite JMPKA0, 48, 32 {
offset 24, 16 offset 24, 32
patch JMPKA0,0,0 { } patch JMPKA0,0,0 { }
} }
@ -77,7 +77,7 @@ Sprite "KCPLD0", 130, 108
{ {
XScale 4 XScale 4
YScale 4 YScale 4
Offset 64, 52 Offset 64, 100
Patch "sprites/cacoplush/cacoplushie_pickup.png", 0, 0 Patch "sprites/cacoplush/cacoplushie_pickup.png", 0, 0
} }
@ -111,7 +111,7 @@ Sprite "KCPLG0", 130, 108
Sprite "KSPRB0", 48, 48 Sprite "KSPRB0", 48, 48
{ {
Offset 24, 24 Offset 24, 48
Patch KSPRB0,0,0 { } Patch KSPRB0,0,0 { }
} }

View File

@ -8,17 +8,17 @@
const HDLD_KIRI_CACOPLUSHIE = "kac"; const HDLD_KIRI_CACOPLUSHIE = "kac";
const KIRI_CACOPLUSHIE_FAINTED_MONSTER_COOLDOWN = 60; const KIRI_CACOPLUSHIE_FAINTED_MONSTER_COOLDOWN = 60;
const KIRI_CACOPLUSHIE_CLASS = "Trilobite"; const KIRI_CACOPLUSHIE_CLASS = "FlyZapper";
// For testing out shield mechanics, if we ever open this up to other // For testing out shield mechanics, if we ever open this up to other
// monster types... // monster types...
// //
// const KIRI_CACOPLUSHIE_CLASS = "PainLord"; // const KIRI_CACOPLUSHIE_CLASS = "Baron";
// //
// Hey, want to see something totally broken? Spawn an imp healer and // Hey, want to see something totally broken? Spawn an imp healer and
// raise an army! // raise an army!
// //
// const KIRI_CACOPLUSHIE_CLASS = "Regentipede"; // const KIRI_CACOPLUSHIE_CLASS = "HealerImp";
const KIRI_CACOPLUSHIE_WEAPONSTATUS_MONSTER_HEALTH = 1; const KIRI_CACOPLUSHIE_WEAPONSTATUS_MONSTER_HEALTH = 1;
const KIRI_CACOPLUSHIE_WEAPONSTATUS_MONSTER_SHIELD = 2; const KIRI_CACOPLUSHIE_WEAPONSTATUS_MONSTER_SHIELD = 2;
@ -77,6 +77,7 @@ class KiriCacodemonPlushie : HDWeapon {
"Fido", "Fido",
"Thor", "Thor",
"Loki", "Loki",
"Bucky",
"Taiyo", "Taiyo",
"Fluffy", "Fluffy",
"Leonardo", "Leonardo",
@ -284,8 +285,8 @@ class KiriCacodemonPlushie : HDWeapon {
A_StartSound("potion/chug"); A_StartSound("potion/chug");
invoker.owner.A_TakeInventory("SecondBlood", 1, TIF_NOTAKEINFINITE); invoker.owner.A_TakeInventory("SecondBlood", 1, TIF_NOTAKEINFINITE);
invoker.setMonsterHealth( invoker.setMonsterHealth(
invoker.getMonsterHealth() + int(invoker.getMonsterHealth() +
invoker.getMonsterMaxHealth() * 0.25); invoker.getMonsterMaxHealth() * 0.25));
// Throw out a spend blood bag. // Throw out a spend blood bag.
A_SpawnItemEx( A_SpawnItemEx(
@ -303,13 +304,14 @@ class KiriCacodemonPlushie : HDWeapon {
HDBleedingWound hbl = HDBleedingWound.inflict( HDBleedingWound hbl = HDBleedingWound.inflict(
invoker.owner, 2, 1, source : invoker.owner); invoker.owner, 2, 1, source : invoker.owner);
HDPlayerPawn(invoker.owner).bloodloss += 0.1; // FIXME this gets rounded down to 0
//HDPlayerPawn(invoker.owner).bloodloss += 0.1;
A_StartSound(invoker.owner.painsound); A_StartSound(invoker.owner.painsound);
invoker.setMonsterHealth( invoker.setMonsterHealth(
invoker.getMonsterHealth() + int(invoker.getMonsterHealth() +
invoker.getMonsterMaxHealth() * 0.1); invoker.getMonsterMaxHealth() * 0.1));
} }
} }

View File

@ -84,7 +84,7 @@ class GretchenCounter : HDWeapon
weaponstatus[KGC_BATTERY] > 0) weaponstatus[KGC_BATTERY] > 0)
{ {
// Discharge rate: 1/1000 chance per tick. // Discharge rate: 1/1000 chance per tick.
int r = random(0, 4000); int r = random(0, 16000);
if(r < 2) { if(r < 2) {
weaponstatus[KGC_BATTERY] -= 1; weaponstatus[KGC_BATTERY] -= 1;
} }

View File

@ -85,7 +85,7 @@ class SnekTechEventHandler : EventHandler
DoSnekTechBackpackSpawnCheck( DoSnekTechBackpackSpawnCheck(
e.Thing, e.Thing,
SNEKTECH_SPRAYCAN, SNEKTECH_SPRAYCAN,
"Sprayer"); "SnekTechSprayer");
} }
override void CheckReplacement(ReplaceEvent e) override void CheckReplacement(ReplaceEvent e)
@ -100,8 +100,8 @@ class SnekTechEventHandler : EventHandler
DoSnekTechReplacement( DoSnekTechReplacement(
SNEKTECH_GRETCHENCOUNTER, SNEKTECH_GRETCHENCOUNTER,
"Stimpack", "GretchenCounter", "PortableStimpack", "GretchenCounter",
12, e); 2, e);
DoSnekTechReplacement( DoSnekTechReplacement(
SNEKTECH_JUMPERCABLES, SNEKTECH_JUMPERCABLES,

View File

@ -1,6 +1,9 @@
// ----------------------------------------------------------------------
// FIXME: Make consts and enums consistent formatting. // Spraypaint cans
// FIXME: Add bulk. // ----------------------------------------------------------------------
//
// Super cheap.
//
const KIRI_SPRAY_DISTANCE = 96; const KIRI_SPRAY_DISTANCE = 96;
const KIRI_SPRAY_SHAKEANIM_MAXANGLE = 20.0; const KIRI_SPRAY_SHAKEANIM_MAXANGLE = 20.0;
@ -18,7 +21,7 @@ enum KiriSprayerStatus
KIRI_SPRAY_WS_PRESSURE = 2 KIRI_SPRAY_WS_PRESSURE = 2
} }
class Sprayer : HDWeapon class SnekTechSprayer : HDWeapon
{ {
default default
{ {
@ -106,16 +109,14 @@ class Sprayer : HDWeapon
if(invoker.GetPressure() < KIRI_SPRAY_PRESSURE_PER_USE) { if(invoker.GetPressure() < KIRI_SPRAY_PRESSURE_PER_USE) {
invoker.owner.A_Log("Not enough pressure to spray."); invoker.owner.A_Log("Not enough pressure to spray.", true);
} else { } else {
Actor spawnedThing;
bool success;
float zOffset = GunHeight() * 0.8; float zOffset = GunHeight() * 0.8;
FLineTraceData lineTraceData; FLineTraceData lineTraceData;
class<SprayerPattern> sprayerPatternClass = "SprayerPattern"; class<SnekTechSprayerPattern> sprayerPatternClass = "SnekTechSprayerPattern";
// Find the spray pattern class that matches the // Find the spray pattern class that matches the
// player's CVar for selected pattern. // player's CVar for selected pattern.
@ -123,10 +124,10 @@ class Sprayer : HDWeapon
"snektech_spraypattern", "snektech_spraypattern",
invoker.owner.player).GetString(); invoker.owner.player).GetString();
for(int i = 0; i < AllActorClasses.size(); i++) { for(int i = 0; i < AllActorClasses.size(); i++) {
class<SprayerPattern> thisPatternClass = (class<SprayerPattern>)(AllActorClasses[i]); class<SnekTechSprayerPattern> thisPatternClass = (class<SnekTechSprayerPattern>)(AllActorClasses[i]);
if(thisPatternClass) { if(thisPatternClass) {
if(thisPatternClass.GetClassName() == currentSprayCVar) { if(thisPatternClass.GetClassName() == currentSprayCVar) {
sprayerPatternClass = (class<SprayerPattern>)(AllActorClasses[i]); sprayerPatternClass = (class<SnekTechSprayerPattern>)(AllActorClasses[i]);
break; break;
} }
} }
@ -151,15 +152,12 @@ class Sprayer : HDWeapon
"kiri/spraycan_spray", "kiri/spraycan_spray",
CHAN_WEAPON); CHAN_WEAPON);
[success, spawnedThing] = A_SpawnItemEx( let normal = lineTraceData.HitDir;
"SprayerDecalSpawner", let spawnedThing = Actor.Spawn("SnekTechSprayerDecalSpawner", lineTraceData.HitLocation - normal);
xofs : 0, yofs : 0, zofs : zOffset); SnekTechSprayerDecalSpawner spawner = SnekTechSprayerDecalSpawner(spawnedThing);
SprayerDecalSpawner spawner = SprayerDecalSpawner(spawnedThing); if(spawner) {
spawner.angle = VectorAngle(-normal.x, -normal.y);
if(success && spawner) {
spawner.A_SetPitch(pitch);
spawner.A_SetAngle(angle);
spawner.actualDecalName = actualDecalName; spawner.actualDecalName = actualDecalName;
spawner.master = invoker.owner; spawner.master = invoker.owner;
@ -169,15 +167,19 @@ class Sprayer : HDWeapon
} else { } else {
invoker.owner.A_Log("Not close enough to a wall to spray."); invoker.owner.A_Log("Not close enough to a wall to spray.", true);
} }
} }
} }
goto waiting; goto waiting;
unload:
KSPR A 2 { invoker.CycleSprayPattern(-1); }
goto waiting;
firemode: firemode:
KSPR A 2 { invoker.CycleSprayPattern(); } KSPR A 2 { invoker.CycleSprayPattern(1); }
goto waiting; goto waiting;
waiting: waiting:
@ -245,8 +247,8 @@ class Sprayer : HDWeapon
} }
int time = level.TotalTime; int time = level.TotalTime;
int lastChargedTime = round( int lastChargedTime = int(round(
float(pressure - KIRI_SPRAY_MAXPRESSURE) / float(KIRI_SPRAY_PRESSURE_DECAY_RATE) + time); float(pressure - KIRI_SPRAY_MAXPRESSURE) / float(KIRI_SPRAY_PRESSURE_DECAY_RATE) + time));
weaponstatus[KIRI_SPRAY_WS_PRESSURE] = lastChargedTime; weaponstatus[KIRI_SPRAY_WS_PRESSURE] = lastChargedTime;
} }
@ -295,13 +297,13 @@ class Sprayer : HDWeapon
ret.clear(); ret.clear();
for(int i = 0; i < AllActorClasses.Size(); i++) { for(int i = 0; i < AllActorClasses.Size(); i++) {
class<Actor> c = AllActorClasses[i]; class<Actor> c = AllActorClasses[i];
if(c is "SprayerPattern" && c != "SprayerPattern") { if(c is "SnekTechSprayerPattern" && c != "SnekTechSprayerPattern") {
ret.push(c.GetClassName()); ret.push(c.GetClassName());
} }
} }
} }
void CycleSprayPattern() void CycleSprayPattern(int increment)
{ {
// Find the current entry in the list of patterns. // Find the current entry in the list of patterns.
String currentPattern = CVar.GetCVar("snektech_spraypattern", owner.player).GetString(); String currentPattern = CVar.GetCVar("snektech_spraypattern", owner.player).GetString();
@ -315,13 +317,27 @@ class Sprayer : HDWeapon
currentIndex = -1; currentIndex = -1;
} }
// Increment the index. // Increment/decrement the index.
int newIndex = (currentIndex + 1) % patternList.size(); int newIndex = (currentIndex + increment) % patternList.size();
if(newIndex < 0) {
newIndex = patternList.size() - 1;
}
// Set the new CVar. // Set the new CVar.
CVar.GetCVar("snektech_spraypattern", owner.player).SetString(patternList[newIndex]); currentPattern = patternList[newIndex];
currentPattern = CVar.GetCVar("snektech_spraypattern", owner.player).GetString(); // first, update the Actual cvar
owner.A_Log("Selected spray pattern: "..currentPattern); if (owner.PlayerNumber() == consoleplayer)
CVar.FindCVar("snektech_spraypattern").SetString(currentPattern);
// then update the per-player copy so the help text is correct
CVar.GetCVar("snektech_spraypattern", owner.player).SetString(currentPattern);
// Print it.
owner.A_Log(
String.format(
"Selected spray pattern: (%d/%d) %s",
newIndex + 1, patternList.size(),
currentPattern),
true);
// Current pattern is referenced in the help text, so reset // Current pattern is referenced in the help text, so reset
// it. // it.
@ -350,12 +366,13 @@ class Sprayer : HDWeapon
return return
WEPHELP_FIREMODE .. " Cycle pattern (current: "..currentPattern..").\n".. WEPHELP_FIREMODE .. " Cycle pattern (current: "..currentPattern..").\n"..
WEPHELP_UNLOAD .. " Cycle pattern (backwards).\n"..
WEPHELP_ALTFIRE .. " Shake the can.\n".. WEPHELP_ALTFIRE .. " Shake the can.\n"..
WEPHELP_FIRE .. " "..messages[messageIndex % messages.Size()].."\n"; WEPHELP_FIRE .. " "..messages[messageIndex % messages.Size()].."\n";
} }
} }
class SprayerDecalSpawner : Actor class SnekTechSprayerDecalSpawner : Decal
{ {
default default
{ {
@ -369,20 +386,73 @@ class SprayerDecalSpawner : Actor
stop; stop;
} }
int timeSinceLastSpray;
int thisSprayerId; int thisSprayerId;
String actualDecalName; String actualDecalName;
Array<Thinker> decals;
void SpawnDecal()
{
Thinker think;
array<thinker> seen;
// find every decal that Isn't ours
let iter = ThinkerIterator.Create('Thinker', STAT_DECAL);
while (think = iter.Next()) {
// BaseDecal isn't exported to zscript so we have to filter this manually
if (think.GetClassName() == 'BaseDecal') {
seen.Push(think);
}
}
// SpawnDecal checks arg0 for the decal ID/name.
// gzdoom passes string arguments as negated string table indices, so
// we need to cast the decal name to a Name (implicitly adding it to
// the string table), then to an int (to get the index).
args[0] = -int(Name(actualDecalName));
Super.SpawnDecal();
// then find every decal that we spawned
iter.Reinit();
while (think = iter.Next()) {
if (think.GetClassName() == 'BaseDecal' &&
seen.Find(think) == seen.Size())
{
decals.Push(think);
}
}
}
override void OnDestroy()
{
for (let i = 0; i < decals.Size(); i++) {
if (decals[i]) {
decals[i].Destroy();
}
}
}
// Decal::BeginPlay deletes the actor
override void BeginPlay() {Actor.BeginPlay();}
override void PostBeginPlay() override void PostBeginPlay()
{ {
Super.PostBeginPlay(); Super.PostBeginPlay();
A_SprayDecal(actualDecalName, KIRI_SPRAY_DISTANCE);
// copy A_SprayDecal z offset
setz(pos.z + height / 2);
SpawnDecal();
if (decals.Size() == 0) {
Destroy();
return;
}
// Figure out a new ID number. // Figure out a new ID number.
ThinkerIterator iter = ThinkerIterator.Create("SprayerDecalSpawner"); ThinkerIterator iter = ThinkerIterator.Create("SnekTechSprayerDecalSpawner");
SprayerDecalSpawner otherSpawner; SnekTechSprayerDecalSpawner otherSpawner;
int maxId = 0; int maxId = 0;
while(otherSpawner = SprayerDecalSpawner(iter.Next())) { while(otherSpawner = SnekTechSprayerDecalSpawner(iter.Next())) {
if(otherSpawner == self) { if(otherSpawner == self) {
continue; continue;
@ -398,121 +468,111 @@ class SprayerDecalSpawner : Actor
thisSprayerId = maxId + 1; thisSprayerId = maxId + 1;
// Clear old sprayers. // Clear old sprayers.
iter = ThinkerIterator.Create("SprayerDecalSpawner"); iter = ThinkerIterator.Create("SnekTechSprayerDecalSpawner");
while(otherSpawner = SprayerDecalSpawner(iter.Next())) { while(otherSpawner = SnekTechSprayerDecalSpawner(iter.Next())) {
if(otherSpawner == self) { if(otherSpawner == self) {
continue; continue;
} }
if(otherSpawner.thisSprayerId < (thisSprayerId - 5)) { int maxSpraysPerPlayer =
CVar.GetCVar("snektech_maxspraysperplayer").GetInt();
if(otherSpawner.thisSprayerId <= (thisSprayerId - maxSpraysPerPlayer)) {
if(otherSpawner.master == master) { if(otherSpawner.master == master) {
otherSpawner.Destroy(); otherSpawner.Destroy();
} }
} }
} }
} }
override void Tick()
{
super.Tick();
timeSinceLastSpray++;
if(timeSinceLastSpray >= 35 * 60) {
A_SprayDecal(actualDecalName, KIRI_SPRAY_DISTANCE);
timeSinceLastSpray = 0;
}
}
} }
class SprayerPattern : Actor class SnekTechSprayerPattern : Actor
{ {
string decalName; string decalName;
property decalName:decalName; property decalName:decalName;
default { default {
SprayerPattern.decalName "KiriTestDecal"; SnekTechSprayerPattern.decalName "KiriTestDecal";
} }
} }
class SnekSpray_TransPride : SprayerPattern class SnekSpray_TransPride : SnekTechSprayerPattern
{ {
default default
{ {
SprayerPattern.decalName "SnekSpray_TransPride"; SnekTechSprayerPattern.decalName "SnekSpray_TransPride";
} }
} }
class SnekSpray_LesbianPride : SprayerPattern class SnekSpray_LesbianPride : SnekTechSprayerPattern
{ {
default default
{ {
SprayerPattern.decalName "SnekSpray_LesbianPride"; SnekTechSprayerPattern.decalName "SnekSpray_LesbianPride";
} }
} }
class SnekSpray_NBPride : SprayerPattern class SnekSpray_NBPride : SnekTechSprayerPattern
{ {
default default
{ {
SprayerPattern.decalName "SnekSpray_NBPride"; SnekTechSprayerPattern.decalName "SnekSpray_NBPride";
} }
} }
class SnekSpray_AcePride : SprayerPattern class SnekSpray_AcePride : SnekTechSprayerPattern
{ {
default default
{ {
SprayerPattern.decalName "SnekSpray_AcePride"; SnekTechSprayerPattern.decalName "SnekSpray_AcePride";
} }
} }
class SnekSpray_ProgressPride : SprayerPattern class SnekSpray_ProgressPride : SnekTechSprayerPattern
{ {
default default
{ {
SprayerPattern.decalName "SnekSpray_ProgressPride"; SnekTechSprayerPattern.decalName "SnekSpray_ProgressPride";
} }
} }
class SnekSpray_DemiPride : SprayerPattern class SnekSpray_DemiPride : SnekTechSprayerPattern
{ {
default default
{ {
SprayerPattern.decalName "SnekSpray_DemiPride"; SnekTechSprayerPattern.decalName "SnekSpray_DemiPride";
} }
} }
class SnekSpray_PanPride : SprayerPattern class SnekSpray_PanPride : SnekTechSprayerPattern
{ {
default default
{ {
SprayerPattern.decalName "SnekSpray_PanPride"; SnekTechSprayerPattern.decalName "SnekSpray_PanPride";
} }
} }
class SnekSpray_SwitchPride : SprayerPattern class SnekSpray_SwitchPride : SnekTechSprayerPattern
{ {
default default
{ {
SprayerPattern.decalName "SnekSpray_SwitchPride"; SnekTechSprayerPattern.decalName "SnekSpray_SwitchPride";
} }
} }
class SnekSpray_BiPride : SprayerPattern class SnekSpray_BiPride : SnekTechSprayerPattern
{ {
default default
{ {
SprayerPattern.decalName "SnekSpray_BiPride"; SnekTechSprayerPattern.decalName "SnekSpray_BiPride";
} }
} }
class SnekSpray_GayPride : SprayerPattern class SnekSpray_GayPride : SnekTechSprayerPattern
{ {
default default
{ {
SprayerPattern.decalName "SnekSpray_GayPride"; SnekTechSprayerPattern.decalName "SnekSpray_GayPride";
} }
} }