Custom sprays can now work in theory.

spraycans
Kiri 2023-09-09 12:31:23 -07:00
parent 4d5e7f1d0e
commit a521cd6074
10 changed files with 283 additions and 22 deletions

View File

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

View File

@ -10,3 +10,17 @@ decal KiriTestDecal
animator KiriInstantFade
randomflipx
}
decal SnekSpray_TransPride
{
pic KSPYA0
animator KiriInstantFade
randomflipx
}
decal SnekSpray_LesbianPride
{
pic KSPYB0
animator KiriInstantFade
randomflipx
}

View File

@ -1,5 +1,9 @@
kiri/gretchencounter_click "sounds/gretchencounter_click.ogg"
kiri/gretchencounter_blip "sounds/gretchencounter_blip.ogg"
kiri/gretchencounter_onoff "sounds/gretchencounter_onoff.ogg"
kiri/cacoplushie_throw "sounds/cacoplushie_throw.ogg"
kiri/cacoplushie_despawn "sounds/cacoplushie_despawn.ogg"
kiri/spraycan_rattle "sounds/spraycan_rattle.ogg"
kiri/spraycan_spray "sounds/spraycan_spray.ogg"

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -117,6 +117,14 @@ Sprite "KSPYA0", 250, 150
Patch KSPYA0,0,0 { }
}
Sprite "KSPYB0", 250, 150
{
XScale 2
YScale 2
Offset 125, 75
Patch KSPYB0,0,0 { }
}
Sprite "KSPRB0", 48, 48
{
Offset 24, 24

View File

@ -1,5 +1,18 @@
// FIXME: Make consts and enums consistent formatting.
const KIRI_SPRAYDISTANCE = 96;
const KIRI_SPRAY_SHAKEANIM_MAXANGLE = 20.0;
const KIRI_SPRAY_MAXPAINT = 50;
const KIRI_SPRAY_MAXPRESSURE = 100;
const KIRI_SPRAY_PRESSUREBUILDSCALE = 20;
const KIRI_SPRAY_PRESSURE_PER_USE = (KIRI_SPRAY_MAXPRESSURE / 2);
enum KiriSprayerStatus
{
KIRISPRAYER_PAINT = 1,
KIRISPRAYER_PRESSURE = 2
}
class Sprayer : HDWeapon
{
@ -27,46 +40,239 @@ class Sprayer : HDWeapon
KSPR A 1 { A_WeaponReady(WRF_ALL); A_WeaponBusy(false); }
goto readyend;
reload:
KSPR A 1 offset(0, 20) {
A_OverlayPivot(0, 0.5, 1.0);
A_OverlayRotate(0, 0);
A_StartSound(
"kiri/spraycan_rattle",
CHAN_WEAPON, CHANF_NOSTOP);
}
KSPR A 1 offset(0, 40) { A_OverlayRotate(0, sin(level.time * 5.0) * KIRI_SPRAY_SHAKEANIM_MAXANGLE * 1.0/3.0); }
KSPR A 1 offset(0, 60) { A_OverlayRotate(0, sin(level.time * 5.0) * KIRI_SPRAY_SHAKEANIM_MAXANGLE * 2.0/3.0); }
KSPR A 1 offset(0, 80) {
A_OverlayRotate(0, sin(level.time * 5.0) * KIRI_SPRAY_SHAKEANIM_MAXANGLE);
// Taper off pressure increase amount based on how much
// pressure is in there already.
float pressureIncreaseScale = 1.0 - (
float(invoker.weaponstatus[KIRISPRAYER_PRESSURE]) /
float(KIRI_SPRAY_MAXPRESSURE));
pressureIncreaseScale *= pressureIncreaseScale;
// Add pressure.
invoker.weaponstatus[KIRISPRAYER_PRESSURE] +=
random(0,
KIRI_SPRAY_PRESSUREBUILDSCALE
* invoker.weaponstatus[KIRISPRAYER_PAINT]
/ KIRI_SPRAY_MAXPAINT);
// Cap pressure amount.
if(invoker.weaponstatus[KIRISPRAYER_PRESSURE] > KIRI_SPRAY_MAXPRESSURE) {
invoker.weaponstatus[KIRISPRAYER_PRESSURE] = KIRI_SPRAY_MAXPRESSURE;
}
}
KSPR A 1 offset(0, 60) { A_OverlayRotate(0, sin(level.time * 5.0) * KIRI_SPRAY_SHAKEANIM_MAXANGLE * 2.0/3.0); }
KSPR A 1 offset(0, 40) { A_OverlayRotate(0, sin(level.time * 5.0) * KIRI_SPRAY_SHAKEANIM_MAXANGLE * 1.0/3.0); }
KSPR A 1 offset(0, 20) { A_OverlayRotate(0, 0); }
goto ready;
fire:
KSPR A 2 {
Actor spawnedThing;
bool success;
float zOffset = GunHeight() * 0.8;
FLineTraceData lineTraceData;
if(invoker.weaponstatus[KIRISPRAYER_PRESSURE] < KIRI_SPRAY_PRESSURE_PER_USE) {
bool traceHit = LineTrace(
angle,
KIRI_SPRAYDISTANCE,
pitch,
flags : TRF_THRUACTORS,
offsetz : zOffset,
data : lineTraceData);
invoker.owner.A_Log("Not enough pressure to spray.");
if(traceHit) {
} else {
if(lineTraceData.HitLine) {
Actor spawnedThing;
bool success;
float zOffset = GunHeight() * 0.8;
FLineTraceData lineTraceData;
class<SprayerPattern> sprayerPatternClass = "SprayerPattern";
// Find the spray pattern class that matches the
// player's CVar for selected pattern.
String currentSprayCVar = CVar.GetCVar(
"snektech_spraypattern",
invoker.owner.player).GetString();
for(int i = 0; i < AllActorClasses.size(); i++) {
class<SprayerPattern> thisPatternClass = (class<SprayerPattern>)(AllActorClasses[i]);
if(thisPatternClass) {
if(thisPatternClass.GetClassName() == currentSprayCVar) {
sprayerPatternClass = (class<SprayerPattern>)(AllActorClasses[i]);
break;
}
}
}
// Get the actual decal name out of it.
let defaultSprayClass = GetDefaultByType(sprayerPatternClass);
String actualDecalName = defaultSprayClass.decalName;
// Find a wall to spray on.
bool traceHit = LineTrace(
angle,
KIRI_SPRAYDISTANCE,
pitch,
flags : TRF_THRUACTORS,
offsetz : zOffset,
data : lineTraceData);
if(traceHit && lineTraceData.HitLine) {
A_StartSound(
"kiri/spraycan_spray",
CHAN_WEAPON);
console.printf("spray spray spray");
[success, spawnedThing] = A_SpawnItemEx(
"SprayerDecalSpawner",
xofs : 0, yofs : 0, zofs : zOffset);
if(success) {
spawnedThing.A_SetPitch(pitch);
spawnedThing.A_SetAngle(angle);
spawnedThing.master = invoker.owner;
SprayerDecalSpawner spawner = SprayerDecalSpawner(spawnedThing);
if(success && spawner) {
spawner.A_SetPitch(pitch);
spawner.A_SetAngle(angle);
spawner.actualDecalName = actualDecalName;
spawner.master = invoker.owner;
invoker.weaponstatus[KIRISPRAYER_PRESSURE] -= KIRI_SPRAY_PRESSURE_PER_USE;
invoker.weaponstatus[KIRISPRAYER_PAINT] -= 1;
}
} else {
invoker.owner.A_Log("Not close enough to a wall to spray.");
}
}
}
goto waiting;
altfire:
KSPR A 2 { invoker.CycleSprayPattern(); }
goto waiting;
waiting:
KSPR A 5;
KSPR A 0 A_Refire("waiting");
KSPR A 0 A_Refire("waiting");
goto ready;
select0:
KSPR A 0 offset(0, 120);
---- A 1 A_Raise(12);
wait;
deselect0:
KSPR A 0;
---- A 1 A_Lower(12);
wait;
}
override void InitializeWepStats(bool idfa)
{
super.InitializeWepStats(idfa);
weaponstatus[KIRISPRAYER_PRESSURE] = 0;
// Add a little bit of randomness to the amount of paint in
// the can.
weaponstatus[KIRISPRAYER_PAINT] =
KIRI_SPRAY_MAXPAINT
- random(0, KIRI_SPRAY_MAXPAINT / 10);
}
override void Tick()
{
super.Tick();
// Gradually decay pressure.
if(random(0, 256) < 4) {
weaponstatus[KIRISPRAYER_PRESSURE] -= 1;
if(weaponstatus[KIRISPRAYER_PRESSURE] < 0) {
weaponstatus[KIRISPRAYER_PRESSURE] = 0;
}
}
}
override void DrawHUDStuff(
HDStatusBar statusBar, HDWeapon weapon,
HDPlayerPawn pawn)
{
// Current pressure (top bar).
statusBar.DrawWepNum(
weaponstatus[KIRISPRAYER_PRESSURE],
KIRI_SPRAY_MAXPRESSURE, posy:-10);
// Total paint remaining (bottom bar).
statusBar.DrawWepNum(
weaponstatus[KIRISPRAYER_PAINT],
KIRI_SPRAY_MAXPAINT);
}
void GetSprayPatternList(Array<String> ret)
{
ret.clear();
for(int i = 0; i < AllActorClasses.Size(); i++) {
class<Actor> c = AllActorClasses[i];
if(c is "SprayerPattern" && c != "SprayerPattern") {
ret.push(c.GetClassName());
}
}
}
void CycleSprayPattern()
{
// Find the current entry in the list of patterns.
String currentPattern = CVar.GetCVar("snektech_spraypattern", owner.player).GetString();
Array<String> patternList;
GetSprayPatternList(patternList);
int currentIndex = patternList.find(currentPattern);
// Make sure we're actually in the list (CVar might not be in
// list, due to mods getting shuffled around and whatever).
if(currentIndex >= patternList.size()) {
currentIndex = -1;
}
// Increment the index.
int newIndex = (currentIndex + 1) % patternList.size();
// Set the new CVar.
CVar.GetCVar("snektech_spraypattern", owner.player).SetString(patternList[newIndex]);
currentPattern = CVar.GetCVar("snektech_spraypattern", owner.player).GetString();
invoker.owner.A_Log("Selected spray pattern: "..currentPattern);
// Current pattern is referenced in the help text, so reset
// it.
A_SetHelpText();
}
override String GetHelpText()
{
super.GetHelpText();
int messageIndex = level.time; //(level.time / 60);
Array<String> messages = {
"Deface the tyrant's property.",
"Engage in civil disobedience.",
"Create a beautiful work of art.",
"Show the world that you still exist.",
"Defy the tyrant."
};
String currentPattern = CVar.GetCVar("snektech_spraypattern", owner.player).GetString();
return
WEPHELP_ALTFIRE.. " Cycle pattern (current: "..currentPattern..").\n"..
WEPHELP_RELOAD .. " Shake the can.\n"..
WEPHELP_FIRE .. " "..messages[messageIndex % messages.Size()].."\n";
}
}
@ -86,12 +292,12 @@ class SprayerDecalSpawner : Actor
int timeSinceLastSpray;
int thisSprayerId;
String actualDecalName;
override void PostBeginPlay()
{
Super.PostBeginPlay();
console.printf("SPRAY");
A_SprayDecal("KiriTestDecal", KIRI_SPRAYDISTANCE);
A_SprayDecal(actualDecalName, KIRI_SPRAYDISTANCE);
// Figure out a new ID number.
ThinkerIterator iter = ThinkerIterator.Create("SprayerDecalSpawner");
@ -131,12 +337,40 @@ class SprayerDecalSpawner : Actor
override void Tick()
{
super.Tick();
timeSinceLastSpray++;
if(timeSinceLastSpray >= 35 * 60) {
A_SprayDecal("KiriTestDecal", KIRI_SPRAYDISTANCE);
A_SprayDecal(actualDecalName, KIRI_SPRAYDISTANCE);
timeSinceLastSpray = 0;
}
}
}
class SprayerPattern : Actor
{
string decalName;
property decalName:decalName;
default {
SprayerPattern.decalName "KiriTestDecal";
}
}
class SnekSpray_TransPride : SprayerPattern
{
default
{
SprayerPattern.decalName "SnekSpray_TransPride";
}
}
class SnekSpray_LesbianPride : SprayerPattern
{
default
{
SprayerPattern.decalName "SnekSpray_LesbianPride";
}
}