| @@ -872,6 +872,11 @@ let macro = | |||
| "stages": 3 | |||
| }, | |||
| "breathEnabled": false, | |||
| "baseBreathArea": 10, | |||
| "breathStyle": "cone", | |||
| get breathArea() { return this.scaling(this.baseBreathArea, this.scale, 2); }, | |||
| "pawVoreEnabled": false, | |||
| "pawsVore": { | |||
| @@ -3678,6 +3683,62 @@ function paw_vore() | |||
| macro.arouse(5); | |||
| } | |||
| function breath(type, style) { | |||
| let area = macro.breathArea; | |||
| let prey = new Container(); | |||
| if (style == "line") { | |||
| area *= 10; | |||
| prey = getOnePrey(biome, area, true); | |||
| } else if (style == "cone") { | |||
| prey = getPrey(biome, area, true); | |||
| } | |||
| let line = describe("breath-" + type, prey, macro, verbose); | |||
| let linesummary = summarize(prey.sum(), true); | |||
| let preyMass = prey.sum_property("mass"); | |||
| let sound = getSound("breath", preyMass); | |||
| update([sound, line, linesummary, newline]); | |||
| add_victim_people("breath-" + type, prey); | |||
| } | |||
| function breath_fire() { | |||
| breath("fire", macro.breathStyle); | |||
| } | |||
| function breath_ice() { | |||
| breath("ice", macro.breathStyle); | |||
| } | |||
| function breath_electric() { | |||
| breath("electric", macro.breathStyle); | |||
| } | |||
| function breath_smoke() { | |||
| breath("smoke", macro.breathStyle); | |||
| } | |||
| function breath_radiation() { | |||
| breath("radiation", macro.breathStyle); | |||
| } | |||
| function breath_foul() { | |||
| breath("foul", macro.breathStyle); | |||
| } | |||
| function breath_line() { | |||
| macro.breathStyle = "line"; | |||
| update(["You prepare to exhale a focused line of breath!",newline]); | |||
| } | |||
| function breath_cone() { | |||
| macro.breathStyle = "cone"; | |||
| update(["You prepare to exhale a broad cone of breath!",newline]); | |||
| } | |||
| function cooldown_start(name) { | |||
| let button = document.querySelector("#" + "button-action-" + name); | |||
| let parent = button.parentElement; | |||
| @@ -4417,6 +4478,43 @@ function startGame(e) { | |||
| } | |||
| } | |||
| if (macro.breathEnabled) { | |||
| enable_panel("breath"); | |||
| enable_button("breath_line"); | |||
| enable_button("breath_cone"); | |||
| if (macro.breathFire) { | |||
| enable_button("breath_fire"); | |||
| enable_victim("breath-fire","Incinerated by fiery breath"); | |||
| } | |||
| if (macro.breathIce) { | |||
| enable_button("breath_ice"); | |||
| enable_victim("breath-ice","Frozen in icy breath"); | |||
| } | |||
| if (macro.breathElectric) { | |||
| enable_button("breath_electric"); | |||
| enable_victim("breath-electric","Fried by an electric gale"); | |||
| } | |||
| if (macro.breathSmoke) { | |||
| enable_button("breath_smoke"); | |||
| enable_victim("breath-smoke","Snuffed out by smoke"); | |||
| } | |||
| if (macro.breathRadiation) { | |||
| enable_button("breath_radiation"); | |||
| enable_victim("breath-radiation","Vaporized by radioactive power"); | |||
| } | |||
| if (macro.breathFoul) { | |||
| enable_button("breath_foul"); | |||
| enable_victim("breath-foul","Smothered in humid breath"); | |||
| } | |||
| } | |||
| document.getElementById("button-arousal").innerHTML = (macro.arousalEnabled ? "Arousal On" : "Arousal Off"); | |||
| if (!macro.arousalEnabled) { | |||
| document.getElementById("arousal").style.display = "none"; | |||
| @@ -30,7 +30,8 @@ var actions = ["eat","chew","vomit","stomp","stomp-wedge","flex-toes","kick","an | |||
| "soul-digest","wear-shoe","remove-shoe","wear-sock","remove-sock","stuff-shoe","dump-shoe","stuff-sock","dump-sock","piss","bladder-vore","scat", | |||
| "sheath-toy","slit-toy","breast-toy","melt","solidify","flood","stomp-goo","goo-digest","ass-goo","goo-stomach-pull","goo-stomach-push", | |||
| "goo-bowels-pull","goo-bowels-push","goo-womb-pull","goo-womb-push","goo-balls-pull","goo-balls-push","goo-breasts-pull","goo-breasts-push", | |||
| "goo-tail-pull","goo-tail-push","goo-paws-pull","goo-paws-push","paw-vore","paw-vore-toes","paws","crop-swallow","crop-transfer"]; | |||
| "goo-tail-pull","goo-tail-push","goo-paws-pull","goo-paws-push","paw-vore","paw-vore-toes","paws","crop-swallow","crop-transfer", | |||
| "breath-fire","breath-ice","breath-electric","breath-smoke","breath-radiation","breath-foul"]; | |||
| for (let i=0; i<actions.length; i++) { | |||
| rules[actions[i]] = []; | |||
| @@ -991,6 +992,109 @@ function defaultCropTransfer(container, macro, verbose) { | |||
| return "Your throat squeezes, forcing " + container.describe(verbose) + " out of your crop and in to your stomach."; | |||
| } | |||
| function nonFatalBreath(container, macro, verbose, type, verb) { | |||
| if (macro.breathStyle == "line") { | |||
| return "You exhale a narrow gout of " + type + ", " + verb + " " + container.describe(verbose) + "."; | |||
| } else if (macro.breathStyle == "cone") { | |||
| return "You exhale a broad cone of " + type + ", " + verb + " " + container.describe(verbose) + "."; | |||
| } | |||
| } | |||
| function defaultBreathFire(container, macro, verbose) { | |||
| if (isNonFatal(macro)) { | |||
| return nonFatalBreath(container, macro, verbose, "fire", "blasting"); | |||
| } | |||
| if (isFatal(macro)) { | |||
| if (macro.breathStyle == "line") { | |||
| return "A withering spear of fire gouts from your maw, spearing through " + container.describe(verbose) + " and incinerating it in a torrid display of power."; | |||
| } else if (macro.breathStyle == "cone") { | |||
| return "You exhale a broad cone of powerful fire, burning " + container.describe(verbose) + " to a crisp in an inescapable tide of flames."; | |||
| } | |||
| } | |||
| return "FIRE" + container.describe(verbose); | |||
| } | |||
| function defaultBreathIce(container, macro, verbose) { | |||
| if (isNonFatal(macro)) { | |||
| return nonFatalBreath(container, macro, verbose, "cold", "freezing"); | |||
| } | |||
| if (isFatal(macro)) { | |||
| if (macro.breathStyle == "line") { | |||
| return "You heave a lance of frigid cold from your gullet, freezing a " + container.describe(verbose) + " to the core."; | |||
| } else if (macro.breathStyle == "cone") { | |||
| return "A blizzard erupts from your maw, flash-freezing " + container.describe(verbose) + ". " + (container.count > 1 ? "They" : "It") + " shatters a heartbeat later, reduced to dust by your power."; | |||
| } | |||
| } | |||
| return "ICE" + container.describe(verbose); | |||
| } | |||
| function defaultBreathElectric(container, macro, verbose) { | |||
| if (isNonFatal(macro)) { | |||
| return nonFatalBreath(container, macro, verbose, "electricity", "shocking"); | |||
| } | |||
| if (isFatal(macro)) { | |||
| if (macro.breathStyle == "line") { | |||
| return "A blinding lance of lightning blasts from your spread " + macro.jawDesc(true) + ", cooking a " + container.describe(verbose) + " from the inside out."; | |||
| } else if (macro.breathStyle == "cone") { | |||
| return "You exhale a brilliant, forking spray of lightning. The flickering bolts arc through " + container.describe(verbose) + ", cooking everything to a crisp."; | |||
| } | |||
| } | |||
| return "ELECTRIC" + container.describe(verbose); | |||
| } | |||
| function defaultBreathSmoke(container, macro, verbose) { | |||
| if (isNonFatal(macro)) { | |||
| return nonFatalBreath(container, macro, verbose, "smoke", "smothering"); | |||
| } | |||
| if (isFatal(macro)) { | |||
| if (macro.breathStyle == "line") { | |||
| return "You part your " + macro.jawDesc(true) + " a touch and blow, casting a thin gout of smoke that envelops a " + container.describe(verbose) + ". Your prey is snuffed out like a candle."; | |||
| } else if (macro.breathStyle == "cone") { | |||
| return "You open wide and exhale. A rolling storm of smoke pours forth, smothering " + container.describe(verbose) + " in a pyroclastic flow."; | |||
| } | |||
| } | |||
| return "SMOKE" + container.describe(verbose); | |||
| } | |||
| function defaultBreathRadiation(container, macro, verbose) { | |||
| if (isNonFatal(macro)) { | |||
| return nonFatalBreath(container, macro, verbose, "radiation", "frying"); | |||
| } | |||
| if (isFatal(macro)) { | |||
| if (macro.breathStyle == "line") { | |||
| return "Your depths pour out a narrow beam of crackling green energy, striking a " + container.describe(verbose) + " and frying it to a crisp, turning your prey to dust in the wind."; | |||
| } else if (macro.breathStyle == "cone") { | |||
| return "You part your " + macro.jawDesc(true) + ", roaring as a massive tide of radiation spews forth. It rolls over " + container.describe(verbose) + ", evaporating " + (container.count > 1 ? "them" : "it") + " in seconds."; | |||
| } | |||
| } | |||
| return "RADIATION" + container.describe(verbose); | |||
| } | |||
| function defaultBreathFoul(container, macro, verbose) { | |||
| if (isNonFatal(macro)) { | |||
| return nonFatalBreath(container, macro, verbose, "foul air", "withering"); | |||
| } | |||
| if (isFatal(macro)) { | |||
| if (macro.breathStyle == "line") { | |||
| return "You blow a narrow stream of breath, withering " + container.describe(verbose) + " in a focused torrent of foul, humid fumes."; | |||
| } else if (macro.breathStyle == "cone") { | |||
| return "You yawn wide and sigh, snuffing out " + container.describe(verbose) + " under a tide of hot, humid breath."; | |||
| } | |||
| } | |||
| return "FOUL" + container.describe(verbose); | |||
| } | |||
| // EATING | |||
| rules["eat"].push({ | |||
| @@ -14,7 +14,9 @@ let sounds = { | |||
| "goo": | |||
| ["Splat.", "Squish.", "Squish!", "SQLCH!", "SQLLLLRCH!", "SQQQQUEEEEELLCH!"], | |||
| "vomit": | |||
| ["Hurk.", "Hurrk.", "Bleugh.", "Bleugh!", "Bleeeugh!", "BLEEEUGHK!"] | |||
| ["Hurk.", "Hurrk.", "Bleugh.", "Bleugh!", "Bleeeugh!", "BLEEEUGHK!"], | |||
| "breath": | |||
| ["Woosh.","Fwoosh.","FWOOSH.","FWOOSH!","FWOOOOOOSH!"] | |||
| }; | |||
| function pickByMass(list, mass) { | |||
| @@ -208,6 +208,7 @@ | |||
| <button class="action-part-button" id="action-part-waste">Waste</button> | |||
| <button class="action-part-button" id="action-part-goo">Goo</button> | |||
| <button class="action-part-button" id="action-part-misc">Misc</button> | |||
| <button class="action-part-button" id="action-part-breath">Breath</button> | |||
| <button class="action-part-button" id="action-part-options">Options</button> | |||
| </div> | |||
| @@ -322,6 +323,17 @@ | |||
| <button class="action-button" id="button-action-pouch_absorb">Absorb Pouch</button> | |||
| </div> | |||
| <div class="action-tab" id="actions-breath"> | |||
| <button class="action-button" id="button-action-breath_line">Line Shape</button> | |||
| <button class="action-button" id="button-action-breath_cone">Cone Shape</button> | |||
| <button class="action-button" id="button-action-breath_fire">Fire</button> | |||
| <button class="action-button" id="button-action-breath_ice">Ice</button> | |||
| <button class="action-button" id="button-action-breath_electric">Electric</button> | |||
| <button class="action-button" id="button-action-breath_smoke">Smoke</button> | |||
| <button class="action-button" id="button-action-breath_radiation">Radiation</button> | |||
| <button class="action-button" id="button-action-breath_foul">Foul</button> | |||
| </div> | |||
| <div class="action-tab" id="actions-options"> | |||
| <button class="stat-button" id="button-arousal">Arousal On</button> | |||
| <button class="stat-button" id="button-stroll">Status: Standing</button> | |||
| @@ -1075,6 +1087,37 @@ | |||
| </li> | |||
| </div> | |||
| </div> | |||
| <div class="custom-category"> | |||
| <input autocomplete="off" class="custom-header-checkbox" type="checkbox" id="breathEnabled" name="breathEnabled" /> | |||
| <label class="custom-header" for="breathEnabled">Breath</label> | |||
| <div class="reveal-if-active"> | |||
| <li> | |||
| <input autocomplete="off" type="checkbox" name="breathFire" id="breathFire" /> | |||
| <label for="breathFire">Fire</label> | |||
| </li> | |||
| <li> | |||
| <input autocomplete="off" type="checkbox" name="breathIce" id="breathIce" /> | |||
| <label for="breathIce">Ice</label> | |||
| </li> | |||
| <li> | |||
| <input autocomplete="off" type="checkbox" name="breathElectric" id="breathElectric" /> | |||
| <label for="breathElectric">Electric</label> | |||
| </li> | |||
| <li> | |||
| <input autocomplete="off" type="checkbox" name="breathSmoke" id="breathSmoke" /> | |||
| <label for="breathSmoke">Smoke</label> | |||
| </li> | |||
| <li> | |||
| <input autocomplete="off" type="checkbox" name="breathRadiation" id="breathRadiation" /> | |||
| <label for="breathRadiation">Radiation</label> | |||
| </li> | |||
| <li> | |||
| <input autocomplete="off" type="checkbox" name="breathFoul" id="breathFoul" /> | |||
| <label for="breathFoul">Foul</label> | |||
| </li> | |||
| </div> | |||
| </div> | |||
| </ul> | |||
| </form> | |||
| </div> | |||