From 7e081bf91ffaf8bda05402f860a736edea091cb1 Mon Sep 17 00:00:00 2001 From: Kiri Date: Sun, 3 Sep 2023 10:03:56 -0700 Subject: [PATCH] More caco plushie work. --- sndinfo.txt | 2 + source_data/Makefile | 16 +- sprites/cacoplush/cacoplushie_glowing1.png | Bin 5835 -> 4031 bytes sprites/cacoplush/cacoplushie_glowing2.png | Bin 5755 -> 3982 bytes sprites/cacoplush/cacoplushie_glowing3.png | Bin 5769 -> 4015 bytes sprites/cacoplush/cacoplushie_idle.png | Bin 5172 -> 3629 bytes sprites/cacoplush/cacoplushie_pickup.png | Bin 0 -> 1475 bytes textures.txt | 36 + zscript.zs | 1 + zscript/cacoplushie.zs | 795 +++++++++++++++++++++ 10 files changed, 847 insertions(+), 3 deletions(-) create mode 100644 sprites/cacoplush/cacoplushie_pickup.png create mode 100644 zscript/cacoplushie.zs diff --git a/sndinfo.txt b/sndinfo.txt index 7fdcf02..5d6837c 100644 --- a/sndinfo.txt +++ b/sndinfo.txt @@ -1,3 +1,5 @@ kiri/gretchencounter_click "sounds/kirigretchencounter_click.ogg" kiri/gretchencounter_blip "sounds/kirigretchencounter_blip.ogg" kiri/gretchencounter_onoff "sounds/kirigretchencounter_onoff.ogg" +kiri/cacoplushie_throw "sounds/kiri_caco_throw.ogg" +kiri/cacoplushie_despawn "sounds/kiri_caco_despawn.ogg" diff --git a/source_data/Makefile b/source_data/Makefile index e5aee8a..f59c22d 100644 --- a/source_data/Makefile +++ b/source_data/Makefile @@ -22,8 +22,8 @@ all : \ ../sprites/cacoplush/cacoplushie_idle.png \ ../sprites/cacoplush/cacoplushie_glowing1.png \ ../sprites/cacoplush/cacoplushie_glowing2.png \ - ../sprites/cacoplush/cacoplushie_glowing3.png - + ../sprites/cacoplush/cacoplushie_glowing3.png \ + ../sprites/cacoplush/cacoplushie_pickup.png # Base frames ../sprites/gretchencounter/kgcma0.png : gretchencounter_weaponsprite.aseprite @@ -366,19 +366,29 @@ brightmaps : povsprite.aseprite # 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 diff --git a/sprites/cacoplush/cacoplushie_glowing1.png b/sprites/cacoplush/cacoplushie_glowing1.png index 45be1e4794a99021b15cc99554cf02642352e117..ea813903fbbfcae008fbefc3dc42a06b74d3ee82 100644 GIT binary patch delta 3001 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 delta 4819 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 diff --git a/sprites/cacoplush/cacoplushie_glowing2.png b/sprites/cacoplush/cacoplushie_glowing2.png index 6d54e7eea27ccd9c0efcc94260412d58ebb8ba72..1a62e046cf2654c9301c77e8390bef7f82ac54c6 100644 GIT binary patch delta 2951 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 QCjbBd07*qoM6N<$f?<1phX4Qo diff --git a/sprites/cacoplush/cacoplushie_glowing3.png b/sprites/cacoplush/cacoplushie_glowing3.png index 96fb5f81d02e9fe23eebf805b6386c3edc8a5873..ddd259449a49d27c211559b103baa69eeb4de579 100644 GIT binary patch delta 2984 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 e@xSq382O1b+$7 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 eU(_Gw2eyWzFZo{HeaA2", + "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(); + } + } + + } 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(); + } + + // Copy player colors over. + spawned_thing.translation = invoker.owner.translation; + + // 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"); + + // 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"; + } +}