Feast 2.0!
選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。
 
 
 
 
 

287 行
13 KiB

  1. import { Creature, POV } from '../entity'
  2. import { Damage, DamageType, ConstantDamageFormula, Vigor, Side, GroupAction, CombatTest, Stat, Action, DamageFormula, UniformRandomDamageFormula, PairAction } from '../combat'
  3. import { ImproperNoun, POVPair, ProperNoun, FemalePronouns, RandomWord, Adjective, POVPairArgs, POVSoloArgs, Verb } from '../language'
  4. import { LogLine, LogLines, LogEntry, Newline } from '../interface'
  5. import { VoreType, Stomach, VoreContainer, Vore, NormalContainer, Container } from '../vore'
  6. import { AttackAction, FeedAction, TransferAction, EatenAction } from '../combat/actions'
  7. import { TogetherCondition, ContainerCondition } from '../combat/conditions'
  8. import { InstantKill } from '../combat/effects'
  9. import * as Words from '../words'
  10. import { StatVigorTest } from '../combat/tests'
  11. class MawContainer extends NormalContainer {
  12. consumeVerb = new Verb('grab', 'grabs', 'grabbing', 'grabbed')
  13. releaseVerb = new Verb('release')
  14. struggleVerb = new Verb('struggle', 'struggles', 'struggling', 'struggled')
  15. consumeLines = new POVPair<Vore, Vore>([
  16. [[POV.First, POV.Third], (user, target) => new LogLine(`You snatch ${target.name} up in your jaws`)],
  17. [[POV.Third, POV.First], (user, target) => new LogLine(`${user.name.capital} snatches you up in ${user.pronouns.possessive} maw`)],
  18. [[POV.Third, POV.Third], (user, target) => new LogLine(`${user.name.capital} snatches ${target.name} up in ${user.pronouns.possessive} maw`)]
  19. ])
  20. releaseLines = new POVPair([
  21. [[POV.First, POV.Third], (user, target) => new LogLine(`You let out ${target.name}`)],
  22. [[POV.Third, POV.First], (user, target) => new LogLine(`${user.name.capital} lets you out `)],
  23. [[POV.Third, POV.Third], (user, target) => new LogLine(`${user.name.capital} lets out ${target.name}`)]
  24. ])
  25. struggleLines = new POVPair([
  26. [[POV.First, POV.Third], (user, target) => new LogLine(`You claw your way free of ${target.name}`)],
  27. [[POV.Third, POV.First], (user, target) => new LogLine(`${user.name.capital} forces ${user.pronouns.possessive} way free!`)],
  28. [[POV.Third, POV.Third], (user, target) => new LogLine(`${user.name.capital} escapes from ${target.name}`)]
  29. ])
  30. constructor (owner: Vore, stomach: VoreContainer) {
  31. super(new ImproperNoun('maw'), owner, new Set([VoreType.Oral]), 50)
  32. this.actions.push(new TransferAction(this, stomach))
  33. }
  34. }
  35. class FlexToesAction extends GroupAction {
  36. lines = new POVPairArgs<Creature, Creature, { damage: Damage }>([
  37. [[POV.First, POV.Third], (user, target, args) => new LogLine(`Your toes crush ${target.name} for `, args.damage.renderShort(), ` damage!`)],
  38. [[POV.Third, POV.First], (user, target, args) => new LogLine(`${user.name.capital}'s toes crush you for `, args.damage.renderShort(), ` damage!`)],
  39. [[POV.Third, POV.Third], (user, target, args) => new LogLine(`${user.name.capital}'s toes crush ${target.name} for `, args.damage.renderShort(), ` damage!`)]
  40. ])
  41. describeGroup (user: Creature, targets: Creature[]): LogEntry {
  42. return new LogLine(`Flex your toes. `, this.damage.explain(user))
  43. }
  44. execute (user: Creature, target: Creature): LogEntry {
  45. const damage = this.damage.calc(user, target)
  46. return new LogLines(target.takeDamage(damage), this.lines.run(user, target, { damage: damage }))
  47. }
  48. describe (user: Creature, target: Creature): LogEntry {
  49. return new LogLine(`Flex your toes! `, this.damage.describe(user, target))
  50. }
  51. constructor (private damage: DamageFormula, container: Container) {
  52. super('Flex Toes', 'Flex your toes!', [
  53. new ContainerCondition(container)
  54. ])
  55. }
  56. }
  57. class BootContainer extends NormalContainer {
  58. consumeLines = new POVPair<Vore, Vore>([
  59. [[POV.First, POV.Third], (user, target) => new LogLine(`You stuff ${target.name} into your boot.`)],
  60. [[POV.Third, POV.First], (user, target) => new LogLine(`${user.name.capital} stuffs you in ${user.pronouns.possessive} boot, pinning you between toes and insole.`)],
  61. [[POV.Third, POV.Third], (user, target) => new LogLine(`${user.name.capital} stuffs ${target.name} in ${user.pronouns.possessive} boot.`)]
  62. ])
  63. releaseLines = new POVPair([
  64. [[POV.First, POV.Third], (user, target) => new LogLine(`You dump ${target.name} out from your boot.`)],
  65. [[POV.Third, POV.First], (user, target) => new LogLine(`${user.name.capital} dumps you out from ${user.pronouns.possessive} boot.`)],
  66. [[POV.Third, POV.Third], (user, target) => new LogLine(`${user.name.capital} dumps ${target.name} out from ${user.pronouns.possessive} boot.`)]
  67. ])
  68. struggleLines = new POVPair([
  69. [[POV.First, POV.Third], (user, target) => new LogLine(`You slip out from ${target.name}'s boot.`)],
  70. [[POV.Third, POV.First], (user, target) => new LogLine(`${user.name.capital} squeezes ${user.pronouns.possessive} way free of your footwear!`)],
  71. [[POV.Third, POV.Third], (user, target) => new LogLine(`${user.name.capital} escapes from ${target.name}'s boot.`)]
  72. ])
  73. consumeVerb = new Verb('trap', 'traps', 'trapped', 'trapping')
  74. releaseVerb = new Verb('dump')
  75. struggleVerb = new Verb('struggle', 'struggles', 'struggling', 'struggled')
  76. constructor (owner: Vore) {
  77. super(new ImproperNoun('boot'), owner, new Set(), 50)
  78. const flex = new FlexToesAction(new UniformRandomDamageFormula(new Damage(
  79. { target: Vigor.Health, type: DamageType.Crush, amount: 50 },
  80. { target: Vigor.Stamina, type: DamageType.Crush, amount: 50 },
  81. { target: Vigor.Resolve, type: DamageType.Crush, amount: 50 }
  82. ), 0.5),
  83. this)
  84. this.actions.push(flex)
  85. }
  86. }
  87. const huge = new RandomWord([
  88. new Adjective('massive'),
  89. new Adjective('colossal'),
  90. new Adjective('big ol\''),
  91. new Adjective('heavy'),
  92. new Adjective('crushing'),
  93. new Adjective('huge')
  94. ])
  95. class BiteAction extends AttackAction {
  96. constructor () {
  97. super(new ConstantDamageFormula(new Damage({ amount: 50, type: DamageType.Slash, target: Vigor.Health })))
  98. this.name = "Bite"
  99. }
  100. }
  101. class ChewAction extends GroupAction {
  102. lines: POVPairArgs<Creature, Creature, { damage: Damage }> = new POVPairArgs([
  103. [[POV.First, POV.Third], (user, target, args: { damage: Damage }) => new LogLine(`You chew on ${target.name} for `, args.damage.renderShort(), `!`)],
  104. [[POV.Third, POV.First], (user, target, args: { damage: Damage }) => new LogLine(`${user.name.capital} chews on you for `, args.damage.renderShort(), `!`)],
  105. [[POV.Third, POV.Third], (user, target, args: { damage: Damage }) => new LogLine(`${user.name.capital} chews on ${target.name} for `, args.damage.renderShort(), `!`)]
  106. ])
  107. describeGroup (user: Creature, targets: Creature[]): LogEntry {
  108. return new LogLine('Crunch \'em all. ', this.damage.explain(user))
  109. }
  110. execute (user: Creature, target: Creature): LogEntry {
  111. const damage = this.damage.calc(user, target)
  112. const results: Array<LogEntry> = []
  113. results.push(this.lines.run(user, target, { damage: damage }))
  114. results.push(new LogLine(' '))
  115. results.push(target.takeDamage(damage))
  116. if (target.vigors.Health <= 0) {
  117. if (this.killAction.allowed(user, target)) {
  118. results.push(new Newline())
  119. results.push(this.killAction.execute(user, target))
  120. }
  121. }
  122. return new LogLine(...results)
  123. }
  124. describe (user: Creature, target: Creature): LogEntry {
  125. return new LogLine('Do the crunch')
  126. }
  127. constructor (private damage: DamageFormula, container: Container, private killAction: Action) {
  128. super('Chew', 'Give them the big chew', [
  129. new ContainerCondition(container)
  130. ])
  131. }
  132. }
  133. class StompAction extends GroupAction {
  134. lines: POVPair<Creature, Creature> = new POVPair([
  135. [[POV.First, POV.Third], (user: Creature, target: Creature) => new LogLine(`You flatten ${target.name} under your foot!`)],
  136. [[POV.Third, POV.First], (user: Creature) => new LogLine(`${user.name.capital} flattens you under ${user.pronouns.possessive} ${huge} foot!`)],
  137. [[POV.Third, POV.Third], (user: Creature, target: Creature) => new LogLine(`${user.name.capital} flattens ${target.name} under ${user.pronouns.possessive} ${huge} foot!`)]
  138. ])
  139. execute (user: Creature, target: Creature): LogEntry {
  140. return new LogLines(this.lines.run(user, target), new InstantKill().apply(target))
  141. }
  142. describe (user: Creature, target: Creature): LogEntry {
  143. return new LogLine('Stomp one sucker')
  144. }
  145. describeGroup (user: Creature, targets: Array<Creature>): LogEntry {
  146. return new LogLine('Stomp all ', targets.length.toString(), ' of \'em!')
  147. }
  148. constructor () {
  149. super('Stomp', 'STOMP!', [
  150. new TogetherCondition()
  151. ])
  152. }
  153. }
  154. class DevourAllAction extends GroupAction {
  155. lines: POVPair<Creature, Creature> = new POVPair([
  156. [[POV.First, POV.Third], (user: Creature, target: Creature) => new LogLine(`You scoop up ${target.name}!`)],
  157. [[POV.Third, POV.First], (user: Creature) => new LogLine(`${user.name.capital} scoops you up!`)],
  158. [[POV.Third, POV.Third], (user: Creature, target: Creature) => new LogLine(`${user.name.capital} scoops ${target.name} up!`)]
  159. ])
  160. groupLines = new POVSoloArgs<Creature, { count: number }>([
  161. [[POV.First], (user, args) => new LogLine(`${Words.SwallowSound.allCaps}! All ${args.count} of your prey pour down your ${Words.Slick} throat. They're just ${user.kind.all} chow now`)],
  162. [[POV.Third], (user, args) => new LogLine(`${Words.SwallowSound.allCaps}! All ${args.count} of ${user.pronouns.possessive} prey pour down ${user.name}'s ${Words.Slick} gullet as ${user.pronouns.subjective} ${Words.Swallows.singular}; they're just ${user.kind.all} chow now`)]
  163. ])
  164. execute (user: Creature, target: Creature): LogEntry {
  165. this.container.consume(target)
  166. return new LogLines(this.lines.run(user, target))
  167. }
  168. describe (user: Creature, target: Creature): LogEntry {
  169. return new LogLine('Stomp one sucker')
  170. }
  171. executeGroup (user: Creature, targets: Array<Creature>): LogEntry {
  172. return new LogLines(...targets.filter(target => this.test.test(user, target)).map(target => this.execute(user, target)).concat(
  173. [
  174. new Newline(),
  175. this.groupLines.run(user, { count: targets.length })
  176. ]
  177. ))
  178. }
  179. describeGroup (user: Creature, targets: Array<Creature>): LogEntry {
  180. return new LogLine('Eat all ', targets.length.toString(), ' of \'em!')
  181. }
  182. private test: CombatTest
  183. constructor (private container: VoreContainer) {
  184. super('Devour All', 'GULP!', [
  185. new TogetherCondition()
  186. ])
  187. this.test = new StatVigorTest(Stat.Power)
  188. }
  189. }
  190. export class Withers extends Creature {
  191. title = "Huge Hellhound"
  192. desc = "Will eat your party"
  193. constructor () {
  194. super(
  195. new ProperNoun('Withers'),
  196. new ImproperNoun('hellhound', 'hellhounds'),
  197. FemalePronouns,
  198. { Toughness: 60, Power: 70, Speed: 40, Willpower: 60, Charm: 120 },
  199. new Set(),
  200. new Set([VoreType.Oral]),
  201. 5000)
  202. this.actions.push(new BiteAction())
  203. this.groupActions.push(new StompAction())
  204. this.side = Side.Monsters
  205. const stomach = new Stomach(this, 50, new Damage(
  206. { amount: 300, type: DamageType.Acid, target: Vigor.Health },
  207. { amount: 200, type: DamageType.Crush, target: Vigor.Stamina },
  208. { amount: 200, type: DamageType.Dominance, target: Vigor.Resolve }
  209. ))
  210. stomach.tickLines = new POVPairArgs<Vore, Vore, { damage: Damage }>([
  211. [[POV.First, POV.Third], (user, target, args) => new LogLine(`Your stomach ${Words.Churns.singular} ${target.name} for `, args.damage.renderShort())],
  212. [[POV.Third, POV.First], (user, target, args) => new LogLine(`${user.name.capital}'s stomach ${Words.Churns.singular} you for `, args.damage.renderShort())],
  213. [[POV.Third, POV.Third], (user, target, args) => new LogLine(`${user.name.capital} ${Words.Churns.singular} ${target.name} for `, args.damage.renderShort())]
  214. ])
  215. stomach.digestLines = new POVPair<Vore, Vore>([
  216. [[POV.First, POV.Third], (user, target) => new LogLine(`Your stomach ${Words.Digests.singular} ${target.name}`)],
  217. [[POV.Third, POV.First], (user, target) => new LogLine(`${user.name.capital}'s stomach ${Words.Digests.singular} you`)],
  218. [[POV.Third, POV.Third], (user, target) => new LogLine(`${target.name.capital}'s ${Words.Struggles.present} fades as the ${target.kind.all} is ${Words.Digests.past} by the ${user.kind.all}'s ${stomach.name}.`)]
  219. ])
  220. this.containers.push(stomach)
  221. this.otherActions.push(new FeedAction(stomach))
  222. this.groupActions.push(new DevourAllAction(stomach))
  223. const maw = new MawContainer(this, stomach)
  224. this.otherContainers.push(maw)
  225. this.actions.push(new ChewAction(new UniformRandomDamageFormula(new Damage(
  226. { target: Vigor.Health, type: DamageType.Crush, amount: 10000 }
  227. ), 0.5),
  228. maw,
  229. new TransferAction(maw, stomach)))
  230. const boot = new BootContainer(this)
  231. this.otherContainers.push(boot)
  232. }
  233. }