Compare commits
No commits in common. "9cea72bc2dd968a716d81b5fd23beba6cac7f5e0" and "347c32bb6aa431ad2c4d9a4617923f21cce545f3" have entirely different histories.
9cea72bc2d
...
347c32bb6a
15
README.md
@ -15,7 +15,7 @@ TIMES as many layers of duct tape as the UAC's competing equivalent,
|
|||||||
forming a sturdier, tougher seal than any so-called "actual
|
forming a sturdier, tougher seal than any so-called "actual
|
||||||
well-funded machine shop" could ever hope to achieve.
|
well-funded machine shop" could ever hope to achieve.
|
||||||
|
|
||||||
## Gretchen Counter
|
## Kiri's Gretchen Counter
|
||||||
|
|
||||||
![Gretchen Counter pickup sprite](sprites/gretchencounter/kgcpa0.png)
|
![Gretchen Counter pickup sprite](sprites/gretchencounter/kgcpa0.png)
|
||||||
|
|
||||||
@ -53,7 +53,7 @@ The battery may be accessed (**Unload**/**Reload**) by removing the
|
|||||||
rear battery bay panel. *May exhibit erratic behavior if used with a
|
rear battery bay panel. *May exhibit erratic behavior if used with a
|
||||||
low battery.*
|
low battery.*
|
||||||
|
|
||||||
## Wiring Bypass Kit
|
## Kiri's Wiring Bypass Kit
|
||||||
|
|
||||||
![Wiring Bypass Kit pickup sprite](sprites/jumpercables/jmpka0.png)
|
![Wiring Bypass Kit pickup sprite](sprites/jumpercables/jmpka0.png)
|
||||||
|
|
||||||
@ -118,16 +118,5 @@ Appendix D is unavailable in the Kiri's Discount Wiring Bypass Kit
|
|||||||
manual. To obtain a copy of appendix D, please purchase a subscription
|
manual. To obtain a copy of appendix D, please purchase a subscription
|
||||||
to Kiri's Discount Wiring Bypass Kit: Professional Edition.
|
to Kiri's Discount Wiring Bypass Kit: Professional Edition.
|
||||||
|
|
||||||
## Cursed Cacodemon Plushie
|
|
||||||
|
|
||||||
![Caco plushie pickup sprite](sprites/cacoplush/cacoplushie_pickup.png)
|
|
||||||
|
|
||||||
Some random junk we found in the bin behind SnekTech HQ. Give it to
|
|
||||||
your kid or something as a gift.
|
|
||||||
|
|
||||||
Caution: May bite.
|
|
||||||
|
|
||||||
### How to use
|
|
||||||
|
|
||||||
Loadout code: kac
|
|
||||||
|
|
||||||
|
20
TODO.md
@ -1,20 +0,0 @@
|
|||||||
- ~~Integrate caco plush~~
|
|
||||||
- ~~Makefile for caco plush sprites~~
|
|
||||||
- ~~Fix upper/lowercase consistency between objects~~
|
|
||||||
- ~~Jumper cables~~
|
|
||||||
- ~~Jumper cables ammohandler stuff~~
|
|
||||||
- ~~Fix wiring kit brightmaps~~
|
|
||||||
|
|
||||||
- Caco plush
|
|
||||||
- ~~Caco plush spawnflags~~
|
|
||||||
- ~~Add caco plush to menu~~
|
|
||||||
- ~~Caco plush documentation~~
|
|
||||||
- ~~Brightmaps for caco plush~~
|
|
||||||
- ~~Set actual chance for caco plush spawn~~
|
|
||||||
- Caco plush sprite scaling
|
|
||||||
|
|
||||||
- Headers and comment formatting pass
|
|
||||||
|
|
||||||
- Organize source_data
|
|
||||||
|
|
||||||
|
|
37
gldefs.txt
@ -42,52 +42,21 @@ brightmap sprite kgcpb0
|
|||||||
|
|
||||||
brightmap sprite jmppa0
|
brightmap sprite jmppa0
|
||||||
{
|
{
|
||||||
map "sprites/jumpercables/bright_jmpr_1.png"
|
map "sprites/bright_jmpr_1.png"
|
||||||
disablefullbright
|
disablefullbright
|
||||||
}
|
}
|
||||||
|
|
||||||
brightmap sprite jmppb0
|
brightmap sprite jmppb0
|
||||||
{
|
{
|
||||||
map "sprites/jumpercables/bright_jmpr_2.png"
|
map "sprites/bright_jmpr_2.png"
|
||||||
disablefullbright
|
disablefullbright
|
||||||
}
|
}
|
||||||
|
|
||||||
brightmap sprite jmppc0
|
brightmap sprite jmppc0
|
||||||
{
|
{
|
||||||
map "sprites/jumpercables/bright_jmpr_3.png"
|
map "sprites/bright_jmpr_3.png"
|
||||||
disablefullbright
|
disablefullbright
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------
|
|
||||||
// Caco plushie brightmaps
|
|
||||||
|
|
||||||
brightmap sprite kcplb0
|
|
||||||
{
|
|
||||||
map "sprites/cacoplush/bright_cacoplushie_idle.png"
|
|
||||||
disablefullbright
|
|
||||||
}
|
|
||||||
|
|
||||||
brightmap sprite kcpld0
|
|
||||||
{
|
|
||||||
map "sprites/cacoplush/bright_cacoplushie_pickup.png"
|
|
||||||
disablefullbright
|
|
||||||
}
|
|
||||||
|
|
||||||
brightmap sprite kcple0
|
|
||||||
{
|
|
||||||
map "sprites/cacoplush/bright_cacoplushie_glowing1.png"
|
|
||||||
disablefullbright
|
|
||||||
}
|
|
||||||
|
|
||||||
brightmap sprite kcplf0
|
|
||||||
{
|
|
||||||
map "sprites/cacoplush/bright_cacoplushie_glowing2.png"
|
|
||||||
disablefullbright
|
|
||||||
}
|
|
||||||
|
|
||||||
brightmap sprite kcplg0
|
|
||||||
{
|
|
||||||
map "sprites/cacoplush/bright_cacoplushie_glowing3.png"
|
|
||||||
disablefullbright
|
|
||||||
}
|
|
||||||
|
|
||||||
|
@ -9,6 +9,5 @@ OptionMenu "SnekTechMenu"
|
|||||||
StaticText "----- Item Spawns -----", "Teal"
|
StaticText "----- Item Spawns -----", "Teal"
|
||||||
FlagOption "Gretchen Counter", "snektech_spawnflags", "YesNo", 0
|
FlagOption "Gretchen Counter", "snektech_spawnflags", "YesNo", 0
|
||||||
FlagOption "Wiring Bypass Kit", "snektech_spawnflags", "YesNo", 1
|
FlagOption "Wiring Bypass Kit", "snektech_spawnflags", "YesNo", 1
|
||||||
FlagOption "Cacodemon Plushie", "snektech_spawnflags", "YesNo", 2
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
kiri/gretchencounter_click "sounds/kirigretchencounter_click.ogg"
|
kiri/gretchencounter_click "sounds/kirigretchencounter_click.ogg"
|
||||||
kiri/gretchencounter_blip "sounds/kirigretchencounter_blip.ogg"
|
kiri/gretchencounter_blip "sounds/kirigretchencounter_blip.ogg"
|
||||||
kiri/gretchencounter_onoff "sounds/kirigretchencounter_onoff.ogg"
|
kiri/gretchencounter_onoff "sounds/kirigretchencounter_onoff.ogg"
|
||||||
kiri/cacoplushie_throw "sounds/kiri_caco_throw.ogg"
|
|
||||||
kiri/cacoplushie_despawn "sounds/kiri_caco_despawn.ogg"
|
|
||||||
|
@ -16,19 +16,7 @@ all : \
|
|||||||
../sprites/gretchencounter/kgcpb0.png \
|
../sprites/gretchencounter/kgcpb0.png \
|
||||||
../sprites/gretchencounter/bright_kgcpa0.png \
|
../sprites/gretchencounter/bright_kgcpa0.png \
|
||||||
../sprites/gretchencounter/bright_kgcpb0.png \
|
../sprites/gretchencounter/bright_kgcpb0.png \
|
||||||
../sprites/gretchencounter/bright_kgcmc0.png \
|
../sprites/gretchencounter/bright_kgcmc0.png
|
||||||
../sounds/kiri_caco_despawn.ogg \
|
|
||||||
../sounds/kiri_caco_throw.ogg \
|
|
||||||
../sprites/cacoplush/cacoplushie_idle.png \
|
|
||||||
../sprites/cacoplush/cacoplushie_glowing1.png \
|
|
||||||
../sprites/cacoplush/cacoplushie_glowing2.png \
|
|
||||||
../sprites/cacoplush/cacoplushie_glowing3.png \
|
|
||||||
../sprites/cacoplush/cacoplushie_pickup.png \
|
|
||||||
../sprites/cacoplush/bright_cacoplushie_idle.png \
|
|
||||||
../sprites/cacoplush/bright_cacoplushie_pickup.png \
|
|
||||||
../sprites/cacoplush/bright_cacoplushie_glowing1.png \
|
|
||||||
../sprites/cacoplush/bright_cacoplushie_glowing2.png \
|
|
||||||
../sprites/cacoplush/bright_cacoplushie_glowing3.png
|
|
||||||
|
|
||||||
# Base frames
|
# Base frames
|
||||||
../sprites/gretchencounter/kgcma0.png : gretchencounter_weaponsprite.aseprite
|
../sprites/gretchencounter/kgcma0.png : gretchencounter_weaponsprite.aseprite
|
||||||
@ -365,58 +353,3 @@ brightmaps : povsprite.aseprite
|
|||||||
|
|
||||||
rm tmp?.png
|
rm tmp?.png
|
||||||
|
|
||||||
# ----------------------------------------------------------------------
|
|
||||||
# Caco plush
|
|
||||||
|
|
||||||
# Sounds
|
|
||||||
../sounds/kiri_caco_despawn.ogg : kiri_caco_despawn.wav
|
|
||||||
ffmpeg -i $^ "-filter:a" "volume=1.0" $@
|
|
||||||
|
|
||||||
../sounds/kiri_caco_throw.ogg : kiri_caco_throw.wav
|
|
||||||
ffmpeg -i $^ "-filter:a" "volume=1.0" $@
|
|
||||||
|
|
||||||
# Sprites
|
|
||||||
../sprites/cacoplush/cacoplushie_idle.png : cacoplushie.aseprite
|
|
||||||
aseprite -b $^ \
|
|
||||||
--ignore-layer "brightmap" \
|
|
||||||
--scale 0.77 \
|
|
||||||
--frame-range 0,0 --save-as $@
|
|
||||||
|
|
||||||
../sprites/cacoplush/cacoplushie_pickup.png : cacoplushie.aseprite
|
|
||||||
aseprite -b $^ \
|
|
||||||
--ignore-layer "brightmap" \
|
|
||||||
--frame-range 0,0 \
|
|
||||||
--scale 0.25 \
|
|
||||||
--save-as $@
|
|
||||||
|
|
||||||
../sprites/cacoplush/cacoplushie_glowing1.png \
|
|
||||||
../sprites/cacoplush/cacoplushie_glowing2.png \
|
|
||||||
../sprites/cacoplush/cacoplushie_glowing3.png : cacoplushie.aseprite
|
|
||||||
aseprite -b $^ \
|
|
||||||
--scale 0.77 \
|
|
||||||
--ignore-layer "brightmap" \
|
|
||||||
--frame-range 1,3 --save-as ../sprites/cacoplush/cacoplushie_glowing.png
|
|
||||||
|
|
||||||
|
|
||||||
# Brightmaps
|
|
||||||
../sprites/cacoplush/bright_cacoplushie_idle.png : cacoplushie.aseprite
|
|
||||||
aseprite -b $^ \
|
|
||||||
--layer "brightmap" \
|
|
||||||
--scale 0.77 \
|
|
||||||
--frame-range 0,0 --save-as $@
|
|
||||||
|
|
||||||
../sprites/cacoplush/bright_cacoplushie_pickup.png : cacoplushie.aseprite
|
|
||||||
aseprite -b $^ \
|
|
||||||
--layer "brightmap" \
|
|
||||||
--frame-range 0,0 \
|
|
||||||
--scale 0.25 \
|
|
||||||
--save-as $@
|
|
||||||
|
|
||||||
../sprites/cacoplush/bright_cacoplushie_glowing1.png \
|
|
||||||
../sprites/cacoplush/bright_cacoplushie_glowing2.png \
|
|
||||||
../sprites/cacoplush/bright_cacoplushie_glowing3.png : cacoplushie.aseprite
|
|
||||||
aseprite -b $^ \
|
|
||||||
--scale 0.77 \
|
|
||||||
--layer "brightmap" \
|
|
||||||
--frame-range 1,3 --save-as ../sprites/cacoplush/bright_cacoplushie_glowing.png
|
|
||||||
|
|
||||||
|
Before Width: | Height: | Size: 2.5 KiB |
Before Width: | Height: | Size: 2.3 KiB |
Before Width: | Height: | Size: 2.4 KiB |
Before Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 3.9 KiB |
Before Width: | Height: | Size: 3.9 KiB |
Before Width: | Height: | Size: 3.9 KiB |
Before Width: | Height: | Size: 3.5 KiB |
Before Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 684 B |
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 629 B |
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 656 B |
Before Width: | Height: | Size: 373 B After Width: | Height: | Size: 373 B |
Before Width: | Height: | Size: 342 B After Width: | Height: | Size: 342 B |
Before Width: | Height: | Size: 365 B After Width: | Height: | Size: 365 B |
Before Width: | Height: | Size: 367 B After Width: | Height: | Size: 367 B |
Before Width: | Height: | Size: 357 B After Width: | Height: | Size: 357 B |
Before Width: | Height: | Size: 362 B After Width: | Height: | Size: 362 B |
Before Width: | Height: | Size: 369 B After Width: | Height: | Size: 369 B |
Before Width: | Height: | Size: 350 B After Width: | Height: | Size: 350 B |
Before Width: | Height: | Size: 374 B After Width: | Height: | Size: 374 B |
Before Width: | Height: | Size: 371 B After Width: | Height: | Size: 371 B |
Before Width: | Height: | Size: 367 B After Width: | Height: | Size: 367 B |
Before Width: | Height: | Size: 364 B After Width: | Height: | Size: 364 B |
Before Width: | Height: | Size: 364 B After Width: | Height: | Size: 364 B |
Before Width: | Height: | Size: 363 B After Width: | Height: | Size: 363 B |
Before Width: | Height: | Size: 366 B After Width: | Height: | Size: 366 B |
Before Width: | Height: | Size: 360 B After Width: | Height: | Size: 360 B |
Before Width: | Height: | Size: 369 B After Width: | Height: | Size: 369 B |
Before Width: | Height: | Size: 343 B After Width: | Height: | Size: 343 B |
Before Width: | Height: | Size: 363 B After Width: | Height: | Size: 363 B |
Before Width: | Height: | Size: 365 B After Width: | Height: | Size: 365 B |
Before Width: | Height: | Size: 357 B After Width: | Height: | Size: 357 B |
Before Width: | Height: | Size: 361 B After Width: | Height: | Size: 361 B |
Before Width: | Height: | Size: 367 B After Width: | Height: | Size: 367 B |
Before Width: | Height: | Size: 350 B After Width: | Height: | Size: 350 B |
Before Width: | Height: | Size: 370 B After Width: | Height: | Size: 370 B |
Before Width: | Height: | Size: 369 B After Width: | Height: | Size: 369 B |
Before Width: | Height: | Size: 366 B After Width: | Height: | Size: 366 B |
Before Width: | Height: | Size: 360 B After Width: | Height: | Size: 360 B |
Before Width: | Height: | Size: 360 B After Width: | Height: | Size: 360 B |
Before Width: | Height: | Size: 360 B After Width: | Height: | Size: 360 B |
Before Width: | Height: | Size: 363 B After Width: | Height: | Size: 363 B |
Before Width: | Height: | Size: 359 B After Width: | Height: | Size: 359 B |
36
textures.txt
@ -60,39 +60,3 @@ sprite JMPPC0, 320, 200 {
|
|||||||
patch JMPPC0,0,0 { }
|
patch JMPPC0,0,0 { }
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------
|
|
||||||
// Caco plushie
|
|
||||||
|
|
||||||
// First-person view while holding.
|
|
||||||
Sprite "KCPLB0", 100, 83
|
|
||||||
{
|
|
||||||
Offset -120, -100
|
|
||||||
Patch "sprites/cacoplush/cacoplushie_idle.png", 0, 0
|
|
||||||
}
|
|
||||||
|
|
||||||
// Pickup sprite on the ground.
|
|
||||||
Sprite "KCPLD0", 32, 27
|
|
||||||
{
|
|
||||||
Offset 16, 13
|
|
||||||
Patch "sprites/cacoplush/cacoplushie_pickup.png", 0, 0
|
|
||||||
}
|
|
||||||
|
|
||||||
// Glowing frames.
|
|
||||||
Sprite "KCPLE0", 100, 83
|
|
||||||
{
|
|
||||||
Offset -120, -100
|
|
||||||
Patch "sprites/cacoplush/cacoplushie_glowing1.png", 0, 0
|
|
||||||
}
|
|
||||||
|
|
||||||
Sprite "KCPLF0", 100, 83
|
|
||||||
{
|
|
||||||
Offset -120, -100
|
|
||||||
Patch "sprites/cacoplush/cacoplushie_glowing2.png", 0, 0
|
|
||||||
}
|
|
||||||
|
|
||||||
Sprite "KCPLG0", 100, 83
|
|
||||||
{
|
|
||||||
Offset -120, -100
|
|
||||||
Patch "sprites/cacoplush/cacoplushie_glowing3.png", 0, 0
|
|
||||||
}
|
|
||||||
|
|
||||||
|
@ -3,4 +3,3 @@ version "4.10"
|
|||||||
#include "zscript/snektech.zs"
|
#include "zscript/snektech.zs"
|
||||||
#include "zscript/jumpercables.zs"
|
#include "zscript/jumpercables.zs"
|
||||||
#include "zscript/gretchencounter.zs"
|
#include "zscript/gretchencounter.zs"
|
||||||
#include "zscript/cacoplushie.zs"
|
|
||||||
|
@ -1,812 +0,0 @@
|
|||||||
// ----------------------------------------------------------------------
|
|
||||||
// Cursed Cacodemon Plushie
|
|
||||||
// ----------------------------------------------------------------------
|
|
||||||
//
|
|
||||||
// Scrawled on the tag is the text "Even in death, I will protect you,
|
|
||||||
// and not even the gods can stop me."
|
|
||||||
//
|
|
||||||
|
|
||||||
const HDLD_KIRI_CACOPLUSHIE = "kac";
|
|
||||||
const KIRI_CACOPLUSHIE_FAINTED_MONSTER_COOLDOWN = 60;
|
|
||||||
const KIRI_CACOPLUSHIE_CLASS = "Trilobite";
|
|
||||||
|
|
||||||
// For testing out shield mechanics, if we ever open this up to other
|
|
||||||
// monster types...
|
|
||||||
//
|
|
||||||
// const KIRI_CACOPLUSHIE_CLASS = "PainLord";
|
|
||||||
//
|
|
||||||
// Hey, want to see something totally broken? Spawn an imp healer and
|
|
||||||
// raise an army!
|
|
||||||
//
|
|
||||||
// const KIRI_CACOPLUSHIE_CLASS = "Regentipede";
|
|
||||||
|
|
||||||
const KIRI_CACOPLUSHIE_WEAPONSTATUS_MONSTER_HEALTH = 1;
|
|
||||||
const KIRI_CACOPLUSHIE_WEAPONSTATUS_MONSTER_SHIELD = 2;
|
|
||||||
const KIRI_CACOPLUSHIE_WEAPONSTATUS_MONSTER_NAME_INDEX = 3;
|
|
||||||
const KIRI_CACOPLUSHIE_WEAPONSTATUS_MONSTER_FAINTED = 4;
|
|
||||||
|
|
||||||
class KiriCacodemonPlushieProjectile : SlowProjectile
|
|
||||||
{
|
|
||||||
// Copied some necessary bits from the normal grenade.
|
|
||||||
default
|
|
||||||
{
|
|
||||||
mass 500;
|
|
||||||
scale 0.3;
|
|
||||||
+bright;
|
|
||||||
}
|
|
||||||
|
|
||||||
// What item threw this?
|
|
||||||
actor thrower;
|
|
||||||
|
|
||||||
states
|
|
||||||
{
|
|
||||||
spawn:
|
|
||||||
APBX BCDE 2 {
|
|
||||||
A_Trail();
|
|
||||||
} loop;
|
|
||||||
}
|
|
||||||
|
|
||||||
override void ExplodeSlowMissile(line blockingline, actor blockingobject)
|
|
||||||
{
|
|
||||||
spawnCritter(blockingobject);
|
|
||||||
destroy();
|
|
||||||
}
|
|
||||||
|
|
||||||
action void spawnCritter(actor beaned_actor)
|
|
||||||
{
|
|
||||||
KiriCacodemonPlushie plushie = KiriCacodemonPlushie(invoker.thrower);
|
|
||||||
|
|
||||||
if(plushie) {
|
|
||||||
plushie.spawnCritter(invoker, beaned_actor);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class KiriCacodemonPlushie : HDWeapon {
|
|
||||||
|
|
||||||
static const String KIRI_CACOPLUSHIE_NAMES[] = {
|
|
||||||
"<unnamed>",
|
|
||||||
"Billy",
|
|
||||||
"Jimmy",
|
|
||||||
"Bob",
|
|
||||||
"Kiddo",
|
|
||||||
"Lucky",
|
|
||||||
"Daisy",
|
|
||||||
"Murderface Skullslasher",
|
|
||||||
"Monica, Destroyer of Worlds",
|
|
||||||
"Fido",
|
|
||||||
"Thor",
|
|
||||||
"Loki",
|
|
||||||
"Taiyo",
|
|
||||||
"Fluffy",
|
|
||||||
"Leonardo",
|
|
||||||
"Donatello",
|
|
||||||
"Raphael",
|
|
||||||
"Michaelangelo",
|
|
||||||
"Winston",
|
|
||||||
"Egon",
|
|
||||||
"Ray",
|
|
||||||
"Peter",
|
|
||||||
"Zuul",
|
|
||||||
"Gozer",
|
|
||||||
"Slimer",
|
|
||||||
"Janine",
|
|
||||||
"Dana",
|
|
||||||
"Quark",
|
|
||||||
"Odo",
|
|
||||||
"Sisko",
|
|
||||||
"Jake",
|
|
||||||
"Nog",
|
|
||||||
"Rom",
|
|
||||||
"Kira",
|
|
||||||
"Jadzia",
|
|
||||||
"Ezri",
|
|
||||||
"Kor",
|
|
||||||
"Koloth",
|
|
||||||
"Kang",
|
|
||||||
"Garrack",
|
|
||||||
"Bashir",
|
|
||||||
"O'brien",
|
|
||||||
"Taco Works"
|
|
||||||
};
|
|
||||||
|
|
||||||
actor spawned_creature;
|
|
||||||
actor spawned_spawnball;
|
|
||||||
int fainted_monster_despawn_countdown;
|
|
||||||
|
|
||||||
default
|
|
||||||
{
|
|
||||||
+hdweapon.fitsinbackpack;
|
|
||||||
|
|
||||||
+INVENTORY.PERSISTENTPOWER;
|
|
||||||
+INVENTORY.INVBAR;
|
|
||||||
|
|
||||||
inventory.icon "KCPLD0";
|
|
||||||
inventory.pickupsound "misc/p_pkup";
|
|
||||||
inventory.pickupmessage "Picked up a cursed Cacodemon plushie.";
|
|
||||||
inventory.amount 1;
|
|
||||||
inventory.maxamount 1;
|
|
||||||
|
|
||||||
hdweapon.refid HDLD_KIRI_CACOPLUSHIE;
|
|
||||||
|
|
||||||
scale 0.63;
|
|
||||||
|
|
||||||
tag "Cacodemon Plushie";
|
|
||||||
}
|
|
||||||
|
|
||||||
states
|
|
||||||
{
|
|
||||||
spawn:
|
|
||||||
KCPL D 0 -1;
|
|
||||||
stop;
|
|
||||||
|
|
||||||
unload:
|
|
||||||
goto ready;
|
|
||||||
|
|
||||||
firemode:
|
|
||||||
goto ready;
|
|
||||||
|
|
||||||
altfire:
|
|
||||||
goto ready;
|
|
||||||
|
|
||||||
ready:
|
|
||||||
KCPL B 0 { A_WeaponReady(WRF_ALL); A_WeaponBusy(false); }
|
|
||||||
|
|
||||||
// Jump to idle and skip glowing anim if we have a monster or
|
|
||||||
// spawnball out.
|
|
||||||
KCPL B 0 A_JumpIf(!(invoker.spawned_spawnball || invoker.spawned_creature), 4);
|
|
||||||
|
|
||||||
// Glowing animation.
|
|
||||||
KCPL E 3;
|
|
||||||
KCPL F 3;
|
|
||||||
KCPL G 3;
|
|
||||||
KCPL G 0 A_Jump(255, 2); // Skip idle animation.
|
|
||||||
|
|
||||||
// Idle animation.
|
|
||||||
KCPL B 1;
|
|
||||||
KCPL B 0;
|
|
||||||
|
|
||||||
goto readyend;
|
|
||||||
|
|
||||||
waiting:
|
|
||||||
KCPL B 5;
|
|
||||||
KCPL B 0 A_Refire("waiting");
|
|
||||||
goto ready;
|
|
||||||
|
|
||||||
fire:
|
|
||||||
KCPL B 2 offset(0, 20);
|
|
||||||
KCPL B 2 offset(0, 40);
|
|
||||||
KCPL B 2 offset(0, 55) {
|
|
||||||
A_StartSound("kiri/cacoplushie_throw");
|
|
||||||
}
|
|
||||||
|
|
||||||
KCPL B 2 offset(0, 70);
|
|
||||||
KCPL B 0 {
|
|
||||||
if(!invoker.spawned_spawnball && !invoker.spawned_creature) {
|
|
||||||
|
|
||||||
// No spawn ball or monster. Throw a new one.
|
|
||||||
|
|
||||||
A_AlertMonsters();
|
|
||||||
|
|
||||||
bool success;
|
|
||||||
actor newcaconade;
|
|
||||||
|
|
||||||
[success, newcaconade] = A_SpawnItemEx(
|
|
||||||
"KiriCacodemonPlushieProjectile",
|
|
||||||
xofs : cos(invoker.owner.pitch) * -4,
|
|
||||||
yofs : 3, // Offset a little bit for a right handed throw.
|
|
||||||
zofs : invoker.owner.height * 0.88 - sin(invoker.owner.pitch) * -4,
|
|
||||||
xvel : cos(invoker.owner.pitch) * 20,
|
|
||||||
yvel : 0,
|
|
||||||
zvel : -sin(invoker.owner.pitch) * 20,
|
|
||||||
flags : SXF_NOCHECKPOSITION | SXF_TRANSFERPITCH);
|
|
||||||
|
|
||||||
if(success) {
|
|
||||||
|
|
||||||
KiriCacodemonPlushieProjectile newcaconade2 =
|
|
||||||
KiriCacodemonPlushieProjectile(newcaconade);
|
|
||||||
newcaconade2.thrower = invoker;
|
|
||||||
invoker.spawned_spawnball = newcaconade2;
|
|
||||||
invoker.fainted_monster_despawn_countdown =
|
|
||||||
KIRI_CACOPLUSHIE_FAINTED_MONSTER_COOLDOWN;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
// Monster or spawn ball is already out. Recall it.
|
|
||||||
invoker.despawnMonster();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reset help text, now that the context has changed.
|
|
||||||
invoker.A_SetHelpText();
|
|
||||||
}
|
|
||||||
KCPL B 2 offset(0, 70);
|
|
||||||
KCPL B 2 offset(0, 55);
|
|
||||||
KCPL B 2 offset(0, 40);
|
|
||||||
KCPL B 2 offset(0, 20);
|
|
||||||
goto waiting;
|
|
||||||
|
|
||||||
reload:
|
|
||||||
KCPL B 2 offset(0, 20);
|
|
||||||
KCPL B 2 offset(0, 40);
|
|
||||||
KCPL B 2 offset(0, 55);
|
|
||||||
KCPL B 5 offset(0, 70);
|
|
||||||
KCPL B 0 { drinkBloodPack(); }
|
|
||||||
KCPL B 2 offset(0, 70);
|
|
||||||
KCPL B 2 offset(0, 55);
|
|
||||||
KCPL B 2 offset(0, 40);
|
|
||||||
KCPL B 2 offset(0, 20);
|
|
||||||
goto ready;
|
|
||||||
|
|
||||||
select0:
|
|
||||||
KCPL B 0 offset(0, 120);
|
|
||||||
---- B 1 A_Raise(12);
|
|
||||||
wait;
|
|
||||||
|
|
||||||
deselect0:
|
|
||||||
KCPL B 0;
|
|
||||||
---- B 1 A_Lower(12);
|
|
||||||
wait;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
action void drinkBloodPack()
|
|
||||||
{
|
|
||||||
// Refuse to feed active monsters.
|
|
||||||
if(invoker.spawned_creature || invoker.spawned_spawnball) {
|
|
||||||
if(invoker.owner) {
|
|
||||||
invoker.owner.A_Log(
|
|
||||||
String.format(
|
|
||||||
"Cannot feed blood to %s when they're not in their plushie!",
|
|
||||||
invoker.getMonsterName()),
|
|
||||||
true);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Refuse to feed monsters that don't need any more.
|
|
||||||
if(invoker.getMonsterHealth() == invoker.getMonsterMaxHealth()) {
|
|
||||||
if(invoker.owner) {
|
|
||||||
invoker.owner.A_Log(
|
|
||||||
String.format(
|
|
||||||
"%s doesn't need any more food for now.",
|
|
||||||
invoker.getMonsterName()),
|
|
||||||
true);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(invoker.owner.countInv("SecondBlood")) {
|
|
||||||
|
|
||||||
// Consume a bloodbag and add health.
|
|
||||||
A_StartSound("potion/chug");
|
|
||||||
invoker.owner.A_TakeInventory("SecondBlood", 1, TIF_NOTAKEINFINITE);
|
|
||||||
invoker.setMonsterHealth(
|
|
||||||
invoker.getMonsterHealth() +
|
|
||||||
invoker.getMonsterMaxHealth() * 0.25);
|
|
||||||
|
|
||||||
// Throw out a spend blood bag.
|
|
||||||
A_SpawnItemEx(
|
|
||||||
"BloodBagWorn",
|
|
||||||
xofs : 0,
|
|
||||||
yofs : 0,
|
|
||||||
zofs : invoker.owner.height / 2.0,
|
|
||||||
xvel : frandom(0, 10),
|
|
||||||
yvel : frandom(-5, 5),
|
|
||||||
flags : SXF_NOCHECKPOSITION);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
// No bloodbags available. Take health instead.
|
|
||||||
HDBleedingWound hbl = HDBleedingWound.inflict(
|
|
||||||
invoker.owner, 2, 1, source : invoker.owner);
|
|
||||||
|
|
||||||
HDPlayerPawn(invoker.owner).bloodloss += 0.1;
|
|
||||||
|
|
||||||
A_StartSound(invoker.owner.painsound);
|
|
||||||
|
|
||||||
invoker.setMonsterHealth(
|
|
||||||
invoker.getMonsterHealth() +
|
|
||||||
invoker.getMonsterMaxHealth() * 0.1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// These are for allowing multiple copies of this weapon at the
|
|
||||||
// same time, but the only things on it that get stored are the
|
|
||||||
// weaponstatus, meaning that we lose the pointer to the spawned
|
|
||||||
// actor. So we have to despawn any actor we have out before
|
|
||||||
// switching.
|
|
||||||
//
|
|
||||||
// Yes, this means you only get one monster to play with at a
|
|
||||||
// time.
|
|
||||||
override bool AddSpareWeapon(
|
|
||||||
actor newowner)
|
|
||||||
{
|
|
||||||
return AddSpareWeaponRegular(newowner);
|
|
||||||
}
|
|
||||||
|
|
||||||
override hdweapon GetSpareWeapon(actor newowner, bool reverse, bool doselect)
|
|
||||||
{
|
|
||||||
despawnMonster();
|
|
||||||
return GetSpareWeaponRegular(newowner, reverse, doselect);
|
|
||||||
}
|
|
||||||
|
|
||||||
override void beginPlay()
|
|
||||||
{
|
|
||||||
super.beginPlay();
|
|
||||||
setRandomMonsterName();
|
|
||||||
setMonsterHealth(getMonsterMaxHealth());
|
|
||||||
setMonsterShield(getMonsterMaxShield());
|
|
||||||
}
|
|
||||||
|
|
||||||
int getMonsterHealth() const
|
|
||||||
{
|
|
||||||
return weaponstatus[KIRI_CACOPLUSHIE_WEAPONSTATUS_MONSTER_HEALTH];
|
|
||||||
}
|
|
||||||
|
|
||||||
int getMonsterMaxHealth() const
|
|
||||||
{
|
|
||||||
return getDefaultByType(KIRI_CACOPLUSHIE_CLASS).health;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setMonsterHealth(int health)
|
|
||||||
{
|
|
||||||
if(health > getMonsterMaxHealth()) {
|
|
||||||
health = getMonsterMaxHealth();
|
|
||||||
}
|
|
||||||
weaponstatus[KIRI_CACOPLUSHIE_WEAPONSTATUS_MONSTER_HEALTH] = health;
|
|
||||||
|
|
||||||
if(health > getMonsterMaxHealth() / 2.0) {
|
|
||||||
setMonsterFainted(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int getMonsterShield() const
|
|
||||||
{
|
|
||||||
return weaponstatus[KIRI_CACOPLUSHIE_WEAPONSTATUS_MONSTER_SHIELD];
|
|
||||||
}
|
|
||||||
|
|
||||||
int getMonsterMaxShield() const
|
|
||||||
{
|
|
||||||
return getDefaultByType(KIRI_CACOPLUSHIE_CLASS).maxshields;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setMonsterShield(int shield)
|
|
||||||
{
|
|
||||||
if(shield > getMonsterMaxShield()) {
|
|
||||||
shield = getMonsterMaxShield();
|
|
||||||
}
|
|
||||||
|
|
||||||
weaponstatus[KIRI_CACOPLUSHIE_WEAPONSTATUS_MONSTER_SHIELD] = shield;
|
|
||||||
}
|
|
||||||
|
|
||||||
override void DrawHUDStuff(HDStatusBar sb, HDWeapon hdw, HDPlayerPawn hpl)
|
|
||||||
{
|
|
||||||
KiriCacodemonPlushie plushie = KiriCacodemonPlushie(hdw);
|
|
||||||
String monsterName = getMonsterName();
|
|
||||||
int monsterHealth = getMonsterHealth();
|
|
||||||
int monsterShield = getMonsterShield();
|
|
||||||
int monsterFainted = getMonsterFainted();
|
|
||||||
|
|
||||||
if(plushie) {
|
|
||||||
|
|
||||||
// Draw the monster name. Use a green color if it's okay
|
|
||||||
// or a red color if it's fainted.
|
|
||||||
sb.drawstring(
|
|
||||||
sb.psmallfont,
|
|
||||||
monsterName, (-20,-30),
|
|
||||||
sb.DI_TEXT_ALIGN_RIGHT | sb.DI_TRANSLATABLE | sb.DI_SCREEN_CENTER_BOTTOM,
|
|
||||||
monsterFainted ? Font.CR_DARKRED : Font.CR_GREEN);
|
|
||||||
|
|
||||||
// Draw blood packs where we'd normally put ammo.
|
|
||||||
sb.drawimage(
|
|
||||||
"PBLDA0",
|
|
||||||
(-48,-10),
|
|
||||||
sb.DI_SCREEN_CENTER_BOTTOM,
|
|
||||||
scale : (0.75, 0.75));
|
|
||||||
|
|
||||||
sb.drawnum(
|
|
||||||
hpl.countinv("SecondBlood"),
|
|
||||||
-48, -8,
|
|
||||||
sb.DI_SCREEN_CENTER_BOTTOM);
|
|
||||||
|
|
||||||
// TODO: Draw something like blue potions or batteries for
|
|
||||||
// shields?
|
|
||||||
|
|
||||||
// Draw health.
|
|
||||||
sb.drawwepnum(
|
|
||||||
monsterHealth,
|
|
||||||
getMonsterMaxHealth());
|
|
||||||
|
|
||||||
// Draw shield.
|
|
||||||
sb.drawwepnum(
|
|
||||||
monsterShield,
|
|
||||||
getMonsterMaxShield(), posy: -10);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override double weaponbulk()
|
|
||||||
{
|
|
||||||
return 10;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setRandomMonsterName()
|
|
||||||
{
|
|
||||||
weaponstatus[KIRI_CACOPLUSHIE_WEAPONSTATUS_MONSTER_NAME_INDEX] =
|
|
||||||
random(1, KiriCacodemonPlushie.KIRI_CACOPLUSHIE_NAMES.size() - 1);
|
|
||||||
|
|
||||||
A_SetHelpText();
|
|
||||||
}
|
|
||||||
|
|
||||||
String getMonsterName() const
|
|
||||||
{
|
|
||||||
return KiriCacodemonPlushie.KIRI_CACOPLUSHIE_NAMES[
|
|
||||||
weaponstatus[KIRI_CACOPLUSHIE_WEAPONSTATUS_MONSTER_NAME_INDEX]];
|
|
||||||
}
|
|
||||||
|
|
||||||
void despawnMonster()
|
|
||||||
{
|
|
||||||
// Whatever we despawn, play the despawn sound for it.
|
|
||||||
if(spawned_spawnball || spawned_creature) {
|
|
||||||
A_StartSound("kiri/cacoplushie_despawn");
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we have a spawn projectile flying through the air,
|
|
||||||
// despawn that.
|
|
||||||
if(spawned_spawnball) {
|
|
||||||
spawned_spawnball.A_SpawnItemEx("TeleFog");
|
|
||||||
spawned_spawnball.destroy();
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we have the creature in the world, despawn that.
|
|
||||||
if(spawned_creature) {
|
|
||||||
spawned_creature.A_SpawnItemEx("TeleFog");
|
|
||||||
spawned_creature.destroy();
|
|
||||||
|
|
||||||
if(owner) {
|
|
||||||
owner.A_Log(
|
|
||||||
String.format("%s has returned to the plushie.", getMonsterName()),
|
|
||||||
true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Adjust help text because the context changed. Now we can
|
|
||||||
// feed it and possibly deploy it.
|
|
||||||
A_SetHelpText();
|
|
||||||
}
|
|
||||||
|
|
||||||
void setMonsterFainted(bool fainted)
|
|
||||||
{
|
|
||||||
weaponstatus[KIRI_CACOPLUSHIE_WEAPONSTATUS_MONSTER_FAINTED] = fainted;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool getMonsterFainted() const
|
|
||||||
{
|
|
||||||
return weaponstatus[KIRI_CACOPLUSHIE_WEAPONSTATUS_MONSTER_FAINTED];
|
|
||||||
}
|
|
||||||
|
|
||||||
override void DoEffect()
|
|
||||||
{
|
|
||||||
if(spawned_creature) {
|
|
||||||
|
|
||||||
// Check on shields.
|
|
||||||
HDMobBase mob = HDMobBase(spawned_creature);
|
|
||||||
if(mob) {
|
|
||||||
Actor shieldItemActor = mob.FindInventory("HDMagicShield");
|
|
||||||
HDMagicShield shieldItem = HDMagicShield(shieldItemActor);
|
|
||||||
if(shieldItem) {
|
|
||||||
|
|
||||||
// Counteract natural shield regeneration. We want
|
|
||||||
// to limit this to when the monster is asleep.
|
|
||||||
if(shieldItem.amount > getMonsterShield()) {
|
|
||||||
shieldItem.amount = getMonsterShield();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Notify us if shields have dropped below what we
|
|
||||||
// last saw them at.
|
|
||||||
if(shieldItem.amount != getMonsterShield()) {
|
|
||||||
setMonsterShield(shieldItem.amount);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Counteract monster health regeneration. We want to
|
|
||||||
// limit this to when the player feeds the monster.
|
|
||||||
if(spawned_creature.health > getMonsterHealth())
|
|
||||||
{
|
|
||||||
spawned_creature.health = getMonsterHealth();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Notify us if the health has dropped.
|
|
||||||
if(spawned_creature.health != getMonsterHealth())
|
|
||||||
{
|
|
||||||
setMonsterHealth(spawned_creature.health);
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the monster reaches zero health, then despawn it
|
|
||||||
// after a short delay. We still want the death animation
|
|
||||||
// to play out.
|
|
||||||
if(spawned_creature.health <= 0.0) {
|
|
||||||
|
|
||||||
setMonsterFainted(true);
|
|
||||||
|
|
||||||
// On the first frame of the monster being downed,
|
|
||||||
// show the message.
|
|
||||||
if(fainted_monster_despawn_countdown ==
|
|
||||||
KIRI_CACOPLUSHIE_FAINTED_MONSTER_COOLDOWN)
|
|
||||||
{
|
|
||||||
if(owner) {
|
|
||||||
owner.A_Log(String.format("%s has fainted!", getMonsterName()), true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// After some number of frames, actually despawn the
|
|
||||||
// monster.
|
|
||||||
fainted_monster_despawn_countdown -= 1;
|
|
||||||
if(fainted_monster_despawn_countdown <= 0) {
|
|
||||||
despawnMonster();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Spawn green balls.
|
|
||||||
if(spawned_creature) {
|
|
||||||
if(level.time & 1) {
|
|
||||||
double mrad = spawned_creature.radius * 0.3;
|
|
||||||
spawned_creature.A_SpawnParticle(
|
|
||||||
"green", SPF_FULLBRIGHT, 50,
|
|
||||||
frandom(4, 8), 0,
|
|
||||||
frandom(-mrad, mrad), frandom(-mrad, mrad), frandom(0.1, 0.9) * spawned_creature.height,
|
|
||||||
frandom(-0.2, 0.2), frandom(-0.2, 0.2), frandom(0.05, 0.2),
|
|
||||||
frandom(-0.05, 0.05), frandom(-0.05, 0.05), 0.06,
|
|
||||||
startalphaf : 0.8,
|
|
||||||
sizestep : 0.1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
// Monster is inside plushie. Sloooooooooooooowly
|
|
||||||
// regenerate shields, if the monster is awake.
|
|
||||||
if(!getMonsterFainted()) {
|
|
||||||
|
|
||||||
if(getMonsterShield() == -64) {
|
|
||||||
|
|
||||||
// Shields were totally broken. Extremely low chance
|
|
||||||
// to restore shields each frame.
|
|
||||||
if(frandom(0, 100) < 0.1) {
|
|
||||||
if(owner) {
|
|
||||||
owner.A_Log(
|
|
||||||
String.format(
|
|
||||||
"%s's shields have started charging.",
|
|
||||||
getMonsterName()),
|
|
||||||
true);
|
|
||||||
}
|
|
||||||
setMonsterShield(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
// Shields are up and slowly recharging.
|
|
||||||
if(frandom(0, 100) < 5) {
|
|
||||||
setMonsterShield(getMonsterShield() + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override void consolidate()
|
|
||||||
{
|
|
||||||
// Restore shields on level exit.
|
|
||||||
if(!getMonsterFainted()) {
|
|
||||||
setMonsterShield(getMonsterMaxShield());
|
|
||||||
}
|
|
||||||
|
|
||||||
A_SetHelpText();
|
|
||||||
}
|
|
||||||
|
|
||||||
action void spawnCritter(actor spawn_ball, actor beaned_actor)
|
|
||||||
{
|
|
||||||
bool success = false;
|
|
||||||
|
|
||||||
// Handle monsters that have already fainted. They won't
|
|
||||||
// spawn.
|
|
||||||
if(invoker.getMonsterFainted())
|
|
||||||
{
|
|
||||||
if(invoker.owner) {
|
|
||||||
invoker.owner.A_Log(
|
|
||||||
String.format(
|
|
||||||
"%s has fainted and cannot manifest yet.",
|
|
||||||
invoker.getMonsterName()),
|
|
||||||
true);
|
|
||||||
}
|
|
||||||
|
|
||||||
spawn_ball.A_SpawnItemEx("TeleFog");
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
int tries = 0;
|
|
||||||
|
|
||||||
// Offset to spawn at. Absolute directions, not relative.
|
|
||||||
float offset_x = 0;
|
|
||||||
float offset_y = 0;
|
|
||||||
float offset_z = 0;
|
|
||||||
|
|
||||||
// If we hit an enemy in the face, back off of that enemy by
|
|
||||||
// the sum of us and their radius. We already know we can't
|
|
||||||
// spawn inside of it.
|
|
||||||
if(beaned_actor) {
|
|
||||||
offset_x -= cos(spawn_ball.angle) * (beaned_actor.radius + 30);
|
|
||||||
offset_y -= sin(spawn_ball.angle) * (beaned_actor.radius + 30);
|
|
||||||
}
|
|
||||||
|
|
||||||
int extra_flags = 0; // FIXME: Remove this.
|
|
||||||
actor spawned_thing;
|
|
||||||
|
|
||||||
// Cumulative random offset we'll use to jitter the location a
|
|
||||||
// bit in the hopes of finding a valid spot.
|
|
||||||
float random_offset_x = 0;
|
|
||||||
float random_offset_y = 0;
|
|
||||||
|
|
||||||
// We need to give this a LOT of leeway as far as where we can
|
|
||||||
// spawn. The monsters are quite large compared to the
|
|
||||||
// projectile, meaning it can easily get into places that the
|
|
||||||
// monsters can't spawn into, so we need to aggressively
|
|
||||||
// search for a nearby spot to spawn into.
|
|
||||||
while(tries < 30 && !success) {
|
|
||||||
|
|
||||||
// This will add some jitter that will thrash
|
|
||||||
// back-and-forth on both X and Y axes, allowing us to
|
|
||||||
// gradually cover a bigger and bigger potential area.
|
|
||||||
float jitter_amount = 1;
|
|
||||||
if(frandom(0, 1) <= 0.5) {
|
|
||||||
random_offset_x = -abs(random_offset_x) - frandom(0, jitter_amount);
|
|
||||||
} else {
|
|
||||||
random_offset_x = abs(random_offset_x) + frandom(0, jitter_amount);
|
|
||||||
}
|
|
||||||
if(frandom(0, 1) <= 0.5) {
|
|
||||||
random_offset_y = -abs(random_offset_y) - frandom(0, jitter_amount);
|
|
||||||
} else {
|
|
||||||
random_offset_y = abs(random_offset_y) + frandom(0, jitter_amount);
|
|
||||||
}
|
|
||||||
|
|
||||||
// This will move the offset back a bit, away from the
|
|
||||||
// point of contact, and back towards the player, while
|
|
||||||
// also mixing in the jitter we calculated.
|
|
||||||
offset_x -= (spawn_ball.vel.x * 0.3) + random_offset_x;
|
|
||||||
offset_y -= (spawn_ball.vel.y * 0.3) + random_offset_y;
|
|
||||||
|
|
||||||
// Z axis is a little different. We already know the
|
|
||||||
// optimal height to spawn at would be the center of the
|
|
||||||
// sector, vertically, so nudge us, on that axis, towards
|
|
||||||
// the center of the sector. No need for jitter.
|
|
||||||
float sector_center_z =
|
|
||||||
(spawn_ball.ceilingz + spawn_ball.floorz) / 2.0;
|
|
||||||
if(spawn_ball.pos.z + offset_z > sector_center_z) {
|
|
||||||
offset_z -= 2.0;
|
|
||||||
} else if(spawn_ball.pos.z + offset_z < sector_center_z) {
|
|
||||||
offset_z += 2.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
tries += 1;
|
|
||||||
|
|
||||||
// Spawn debug particles showing all the points we've
|
|
||||||
// tried.
|
|
||||||
if(hd_debug > 1) {
|
|
||||||
spawn_ball.A_SpawnParticle(
|
|
||||||
"yellow",
|
|
||||||
flags : 0,
|
|
||||||
size : 12,
|
|
||||||
xoff : offset_x,
|
|
||||||
yoff : offset_y,
|
|
||||||
zoff : offset_z);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Attempt to spawn the monster.
|
|
||||||
[success, spawned_thing] = spawn_ball.A_SpawnItemEx(
|
|
||||||
KIRI_CACOPLUSHIE_CLASS,
|
|
||||||
xofs : offset_x,
|
|
||||||
yofs : offset_y,
|
|
||||||
zofs : offset_z,
|
|
||||||
xvel : 0,
|
|
||||||
yvel : 0,
|
|
||||||
zvel : 0,
|
|
||||||
angle : 0,
|
|
||||||
flags : SXF_SETMASTER | SXF_ABSOLUTEPOSITION | extra_flags);
|
|
||||||
|
|
||||||
if(success) {
|
|
||||||
|
|
||||||
// Spawn succeeded. Stop searching.
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(success) {
|
|
||||||
|
|
||||||
// Copy health over.
|
|
||||||
spawned_thing.health = invoker.getMonsterHealth();
|
|
||||||
|
|
||||||
// Copy shields over (if applicable).
|
|
||||||
Actor shieldItemActor = spawned_thing.FindInventory("HDMagicShield");
|
|
||||||
HDMagicShield shieldItem = HDMagicShield(shieldItemActor);
|
|
||||||
if(shieldItem) {
|
|
||||||
shieldItem.amount = invoker.getMonsterShield();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set the name.
|
|
||||||
spawned_thing.setTag(invoker.getMonsterName());
|
|
||||||
|
|
||||||
// FIXME: Would prefer something to make the monster more
|
|
||||||
// distinct. Other attempts were made to distinguish the
|
|
||||||
// monster...
|
|
||||||
//
|
|
||||||
// This one was good because it made the monsters very
|
|
||||||
// distinct (built-in GZDoom translation):
|
|
||||||
//
|
|
||||||
// spawned_thing.settranslation("Ice")
|
|
||||||
// spawned_thing.translation = TRANSLATION_ICE;
|
|
||||||
//
|
|
||||||
// This would make it render in the transparent style of
|
|
||||||
// the ghosts (minus the coloration):
|
|
||||||
//
|
|
||||||
// spawned_thing.A_SetRenderStyle(1.0, STYLE_ADD);
|
|
||||||
//
|
|
||||||
// This one just made it all purple. Certainly looks
|
|
||||||
// distinct!
|
|
||||||
//
|
|
||||||
// spawned_thing.A_SetTranslation("AllPurple");
|
|
||||||
//
|
|
||||||
// This would just copy the player colors over.
|
|
||||||
//
|
|
||||||
// spawned_thing.translation = invoker.owner.translation;
|
|
||||||
|
|
||||||
// Spawn flash.
|
|
||||||
spawn_ball.A_SpawnItemEx(
|
|
||||||
"TeleFog",
|
|
||||||
xofs : offset_x,
|
|
||||||
yofs : offset_y,
|
|
||||||
zofs : offset_z,
|
|
||||||
flags : SXF_ABSOLUTEPOSITION);
|
|
||||||
|
|
||||||
// Keep track of the spawned creature.
|
|
||||||
invoker.spawned_creature = spawned_thing;
|
|
||||||
|
|
||||||
// If we smacked a mob in the face, then make that the
|
|
||||||
// spawned monster's target immediately.
|
|
||||||
if(beaned_actor) {
|
|
||||||
if(beaned_actor is "HDMobBase") {
|
|
||||||
spawned_thing.target = beaned_actor;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
// Tell the player we failed.
|
|
||||||
if(invoker.owner) {
|
|
||||||
invoker.owner.A_Log(
|
|
||||||
String.format("Failed to summon %s: Not enough room.", invoker.getMonsterName()),
|
|
||||||
true);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override String, double getPickupSprite(bool usespare)
|
|
||||||
{
|
|
||||||
return "KCPLD0";
|
|
||||||
}
|
|
||||||
|
|
||||||
override String getHelpText()
|
|
||||||
{
|
|
||||||
if(spawned_creature || spawned_spawnball) {
|
|
||||||
return WEPHELP_FIRE.." Return "..getMonsterName().." to the plushie.\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
WEPHELP_FIRE .. " Summon "..getMonsterName()..".\n"..
|
|
||||||
WEPHELP_RELOAD .. " Feed blood to "..getMonsterName()..".\n";
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,16 +1,3 @@
|
|||||||
// ----------------------------------------------------------------------
|
|
||||||
// Gretchen Counter
|
|
||||||
// ----------------------------------------------------------------------
|
|
||||||
//
|
|
||||||
// This object clearly looks like it was recycled from a very old
|
|
||||||
// Geiger counter.
|
|
||||||
//
|
|
||||||
// Smells kind of like rotting meat.
|
|
||||||
//
|
|
||||||
// Try not to think about it.
|
|
||||||
//
|
|
||||||
|
|
||||||
|
|
||||||
#include "zscript/snektech.zs"
|
#include "zscript/snektech.zs"
|
||||||
|
|
||||||
const HDLD_KIRI_GRETCHENCOUNTER = "kgc";
|
const HDLD_KIRI_GRETCHENCOUNTER = "kgc";
|
||||||
|
@ -1,14 +1,3 @@
|
|||||||
// ----------------------------------------------------------------------
|
|
||||||
// Wiring Bypass Kit
|
|
||||||
// ----------------------------------------------------------------------
|
|
||||||
//
|
|
||||||
// This is just a pile of electronics maintenance equipment. The usual
|
|
||||||
// stuff is here, like electrical tape, wire cutters, etc.
|
|
||||||
//
|
|
||||||
// There's also a meter that looks like it was made out of some beat
|
|
||||||
// up piece of equipment, and held together with duct tape.
|
|
||||||
//
|
|
||||||
|
|
||||||
const HDLD_KIRI_JUMPERCABLES = "jmp";
|
const HDLD_KIRI_JUMPERCABLES = "jmp";
|
||||||
|
|
||||||
const jumperCablesRaycastRange = 48; // Same range as the DERP.
|
const jumperCablesRaycastRange = 48; // Same range as the DERP.
|
||||||
|
@ -1,15 +1,7 @@
|
|||||||
// ----------------------------------------------------------------------
|
|
||||||
// Snektech
|
|
||||||
// ----------------------------------------------------------------------
|
|
||||||
//
|
|
||||||
// Spawn flags for SnekTech items handled here.
|
|
||||||
//
|
|
||||||
|
|
||||||
enum SnekTechSpawnFlags
|
enum SnekTechSpawnFlags
|
||||||
{
|
{
|
||||||
SNEKTECH_GRETCHENCOUNTER = 0,
|
SNEKTECH_GRETCHENCOUNTER = 0,
|
||||||
SNEKTECH_JUMPERCABLES = 1,
|
SNEKTECH_JUMPERCABLES = 1
|
||||||
SNEKTECH_CACOPLUSHIE = 2
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class SnekTechEventHandler : EventHandler
|
class SnekTechEventHandler : EventHandler
|
||||||
@ -62,7 +54,6 @@ class SnekTechEventHandler : EventHandler
|
|||||||
HDBattery bat = HDBattery(e.Thing);
|
HDBattery bat = HDBattery(e.Thing);
|
||||||
if(bat) {
|
if(bat) {
|
||||||
bat.ItemsThatUseThis.Push("GretchenCounter");
|
bat.ItemsThatUseThis.Push("GretchenCounter");
|
||||||
bat.ItemsThatUseThis.Push("JumperCablesUsable");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete disabled items from backpacks that just spawned.
|
// Delete disabled items from backpacks that just spawned.
|
||||||
@ -75,11 +66,6 @@ class SnekTechEventHandler : EventHandler
|
|||||||
e.Thing,
|
e.Thing,
|
||||||
SNEKTECH_JUMPERCABLES,
|
SNEKTECH_JUMPERCABLES,
|
||||||
"JumperCablesUsable");
|
"JumperCablesUsable");
|
||||||
|
|
||||||
DoSnekTechBackpackSpawnCheck(
|
|
||||||
e.Thing,
|
|
||||||
SNEKTECH_CACOPLUSHIE,
|
|
||||||
"KiriCacodemonPlushie");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override void CheckReplacement(ReplaceEvent e)
|
override void CheckReplacement(ReplaceEvent e)
|
||||||
@ -100,12 +86,7 @@ class SnekTechEventHandler : EventHandler
|
|||||||
DoSnekTechReplacement(
|
DoSnekTechReplacement(
|
||||||
SNEKTECH_JUMPERCABLES,
|
SNEKTECH_JUMPERCABLES,
|
||||||
"Allmap", "JumperCablesUsable",
|
"Allmap", "JumperCablesUsable",
|
||||||
12, e);
|
256, e);
|
||||||
|
|
||||||
DoSnekTechReplacement(
|
|
||||||
SNEKTECH_CACOPLUSHIE,
|
|
||||||
"BlurSphere", "KiriCacodemonPlushie",
|
|
||||||
6, e);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|