being.go 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642
  1. package world
  2. import (
  3. "fmt"
  4. "strings"
  5. )
  6. /* Aptitudes of a being, species or profession */
  7. type Aptitudes struct {
  8. Skills []BeingSkill
  9. Arts []BeingArt
  10. Techniques []BeingTechnique
  11. Exploits []BeingExploit
  12. }
  13. /* Kind of a being or "Kin" for short*/
  14. type Kin struct {
  15. Entity
  16. // Talent modifiers of the species
  17. Talents
  18. // Vitals modifiers of the species
  19. Vitals
  20. Aptitudes
  21. // Arts multiplier in %. If zero arts cannot be used.
  22. Arts float64
  23. // Technique multiplier in %. If zero techniques cannot be used.
  24. Techniques float64
  25. // Learning speed in %
  26. Learning float64
  27. // How much of the being is mechanical.
  28. // Affects healing arts and medication, and the ability to install parts.
  29. Mechanical float64
  30. // Level of Corruption
  31. Corruption float64
  32. // If players can choose this or not
  33. Playable bool
  34. }
  35. func NewKin(id ID, name string) * Kin {
  36. res := new(Kin)
  37. res.ID = id;
  38. res.Name = name
  39. return res
  40. }
  41. /* Job of a being */
  42. type Job struct {
  43. Entity
  44. // Talent modifiers of the profession
  45. Talents
  46. // Vitals modifiers of the profession
  47. Vitals
  48. // Map of skills that this job starts with and their levels.
  49. Skills map[ID] int
  50. // Same for arts and techniques and exploits
  51. Arts map[ID] int
  52. Techniques map[ID] int
  53. Exploits map[ID] int
  54. // if a player can choose this or not
  55. Playable bool
  56. }
  57. /* Gender of a being */
  58. type Gender struct {
  59. Entity
  60. // Talent modifiers of the gender
  61. Talents
  62. // Vitals modifiers of the gender
  63. Vitals
  64. }
  65. /* Struct, list and map of all genders in WOE. */
  66. var Genders = struct {
  67. Female Gender
  68. Male Gender
  69. Intersex Gender
  70. Genderless Gender
  71. }{
  72. Gender {
  73. Entity : Entity{ ID: "female", Name: "Female"},
  74. Talents : Talents { Agility: 1, Charisma: 1 },
  75. },
  76. Gender {
  77. Entity : Entity{ ID: "male", Name: "Male"},
  78. Talents : Talents { Strength: 1, Intelligence: 1 },
  79. },
  80. Gender {
  81. Entity : Entity{ ID: "intersex", Name: "Intersex"},
  82. Talents : Talents { Dexterity: 1, Wisdom: 1 },
  83. },
  84. Gender {
  85. Entity : Entity{ ID: "genderless", Name: "Genderless"},
  86. Talents : Talents { Toughness: 1, Emotion: 1 },
  87. },
  88. }
  89. var GenderList = []*Gender{&Genders.Female, &Genders.Male,
  90. &Genders.Intersex, &Genders.Genderless }
  91. var GenderMap = map[ID]*Gender {
  92. Genders.Female.ID : &Genders.Female,
  93. Genders.Male.ID : &Genders.Male,
  94. Genders.Intersex.ID : &Genders.Intersex,
  95. Genders.Genderless.ID : &Genders.Genderless,
  96. }
  97. /* All Kins of WOE */
  98. var KinList = [] Kin {
  99. { Entity: Entity {
  100. ID: "kin_human", Name: "Human",
  101. Short: "The primordial conscious beings on Earth.",
  102. Long:
  103. `Humans are the primordial kind of conscious beings on Earth.
  104. They excel at nothing in particular, but are fast learners.`,
  105. },
  106. // No talents because humans get no talent bonuses
  107. // No stats either because no bonuses there either.
  108. Arts : 1.0,
  109. Playable : true,
  110. },
  111. { Entity: Entity {
  112. ID: "kin_neosa", Name: "Neosa",
  113. Short: "Nimble beings, skilled in the Arts.",
  114. Long:
  115. `Neosa are descendents of humans genetically modified to be lite, agile
  116. and skilled with the Numen Arts. They are less tough and strong, and less adept
  117. with techniques`,
  118. },
  119. // AGI+1 EMO+1 STR-1 TOU-1
  120. Talents : Talents { Strength : -1, Toughness: -1,
  121. Agility : 1, Emotion : 1, },
  122. Arts : 1.2,
  123. Techniques : 0.8,
  124. Playable : true,
  125. },
  126. { Entity: Entity {
  127. ID: "kin_mantu", Name: "Mantu",
  128. Short: "Hardy, stocky beings, skilled in the Techniques.",
  129. Long:
  130. `Mantu are descendents of humans genetically modified to be hardy, stocky
  131. and skilled with Techniques. They are somewhat less agine and less adept with
  132. Numen Arts than humans.`,
  133. },
  134. // STR+1 1 TOU+1 AGI-1 EMO-1
  135. Talents : Talents { Strength : +1, Toughness: +1,
  136. Agility : -1, Emotion : -1, },
  137. Arts : 0.8,
  138. Techniques : 1.2,
  139. Playable : true,
  140. },
  141. { Entity: Entity {
  142. ID: "kin_cyborg", Name: "Cyborg",
  143. Short: "Human enhanced with robotic parts. ",
  144. Long:
  145. `Cyborgs are humans who either through neccesity or through their own will,
  146. have been enhanced with robotic parts. They are far more skilled with
  147. Techniques, and can install some Parts, but their Nummen arts are only half
  148. as effective. They are partially mechanical and healing arts and medication
  149. is not as effective on them, but they can be repaired.`,
  150. },
  151. // STR+1 1 TOU+1 DEX+1 INT+1
  152. Talents : Talents { Strength : +1, Toughness: +1,
  153. Dexterity : +1, Intelligence: +1, },
  154. Arts : 0.5,
  155. Techniques : 1.5,
  156. Mechanical : 0.5,
  157. Playable : true,
  158. },
  159. { Entity: Entity {
  160. ID: "kin_android", Name: "Android",
  161. Short: "Human shaped biomchanical robot at the service of humans. ",
  162. Long:
  163. `Androids are conscious human shaped robots with the imperative to serve humans.
  164. Highly effective with Techniques, and can install many Parts, but cannot use
  165. any Nummen arts. Since thay are not alive, they technically cannot die.`,
  166. },
  167. // STR+1 1 TOU+1 DEX+1 INT+1
  168. Talents : Talents { Strength : +2, Toughness: +2,
  169. Dexterity : +2, Intelligence: +2, },
  170. Arts : 0.0,
  171. Techniques : 2.0,
  172. Mechanical : 1.0,
  173. Playable : true,
  174. },
  175. { Entity: Entity {
  176. ID: "kin_maverick", Name: "Maverick",
  177. Short: "Human shaped biomechanical robot running wild. ",
  178. Long:
  179. `Mavericks are androids in which the imperative to serve humans has
  180. been destroyed or disabled. Highly effective with Techniques, and can install
  181. many Parts, but cannot use any Nummen arts. Since thay are not alive, they
  182. technically cannot die. They are feared by Humans and hated by Androids.`,
  183. },
  184. // STR+1 1 TOU+1 DEX+1 INT+1
  185. Talents : Talents { Strength : +3, Toughness: +3,
  186. Dexterity : +2, Intelligence: +2, Charisma: -2 },
  187. Arts : 0.0,
  188. Techniques : 2.0,
  189. Mechanical : 1.0,
  190. Playable : false,
  191. },
  192. { Entity: Entity {
  193. ID: "kin_robot", Name: "Robot",
  194. Short: "Non conscious mechanical robot.",
  195. Long:
  196. `In the wars of the past many robots were built for offense or defense.
  197. Unfortunately, they are self repairing and often even able to replicate
  198. if they find suitable materials. No wonder they are still prowling
  199. the Earth millennia after.`,
  200. },
  201. // STR+1 1 TOU+1 DEX+1 INT+1
  202. Talents : Talents { Strength : +4, Toughness: +4,
  203. Dexterity : +2, Intelligence: +2, Charisma: -4},
  204. Arts : 0.0,
  205. Techniques : 2.0,
  206. Mechanical: 1.0,
  207. Playable : false,
  208. },
  209. { Entity: Entity {
  210. ID: "kin_drone", Name: "Drone",
  211. Short: "Flying combat robot. ",
  212. Long:
  213. `Out of control robots are a pain, out of control flying robots even more so!
  214. They might be less though than normal robots, but they move extremely quickly.
  215. `,
  216. },
  217. Talents : Talents { Strength : +2, Toughness: +2,
  218. Agility: +4, Dexterity : +2, Intelligence: +2, Charisma: -4},
  219. Arts : 0.0,
  220. Techniques : 2.0,
  221. Mechanical : 1.0,
  222. Playable : false,
  223. },
  224. { Entity: Entity {
  225. ID: "kin_turret", Name: "Turret",
  226. Short: "Immobile automated defense system. ",
  227. Long:
  228. `
  229. The ancients would set up robotic defense system to guard certain areas.
  230. These defense systems might be immobile, but they are deadly accurate.
  231. Furthermore they are extremely resillient and self repairing.
  232. No wonder they are still actve after all these years.
  233. `,
  234. },
  235. Talents : Talents { Strength : +2, Toughness: +4,
  236. Agility: -4, Dexterity : +4, Intelligence: +4, Charisma: -4},
  237. Arts : 0.0,
  238. Techniques : 2.0,
  239. Mechanical : 1.0,
  240. Playable : false,
  241. },
  242. { Entity: Entity {
  243. ID: "kin_beast", Name: "Beast",
  244. Short: "Beast that prowls the wild. ",
  245. Long:
  246. `Due to the damage to the ecosystem, beasts have rapidly evolved in the last
  247. 60000 years. As a result, most all of them, even the plant eaters, are ferocious
  248. and aggressive, to protect themselves and their offspring from Humans.`,
  249. },
  250. Talents : Talents { Strength : +2, Toughness: +2,
  251. Agility : +1, Intelligence: -5, },
  252. },
  253. { Entity: Entity {
  254. ID: "kin_bird", Name: "Bird",
  255. Short: "Flying being that prowls the wild. ",
  256. Long:
  257. `Beasts can be dangerous, flying beasts are all the more so!
  258. They might be less resillient, but all the more agile.`,
  259. },
  260. Talents : Talents { Strength : +1, Toughness: +1,
  261. Agility : +3, Intelligence: -5, },
  262. },
  263. { Entity: Entity {
  264. ID: "kin_fish", Name: "Fish",
  265. Short: "Fish like being that swims the seas or rivers. ",
  266. Long:
  267. `Now you know why you were always told not to swim in rivers or seas.
  268. Fish dart through the water, attacking with their razor sharp teeth.
  269. `,
  270. },
  271. Talents : Talents { Strength : +3, Toughness: +2,
  272. Agility : +2, Intelligence: -5, },
  273. },
  274. { Entity: Entity {
  275. ID: "kin_amphibian", Name: "Amphibian",
  276. Short: "Being that lives both on land and in the water. ",
  277. Long:
  278. `Covered with a slimy skin and often toxic, these being can not only swim
  279. but also purse you on land.`,
  280. },
  281. Talents : Talents { Strength : +1, Toughness: +2,
  282. Agility : +1, Dexterity: +1, Intelligence: -5, },
  283. },
  284. { Entity: Entity {
  285. ID: "kin_reptile", Name: "Reptile",
  286. Short: "Scaly creepy crawling beasts.",
  287. Long:
  288. `Reptiles have been around for a long time, and it looks they will be around for
  289. a long time still. They may be slow, especially in colder weather, nevertheless
  290. they remain dangerous.
  291. `,
  292. },
  293. Talents : Talents { Strength : +2, Toughness: +2,
  294. Agility: -1, Intelligence: -5, },
  295. },
  296. { Entity: Entity {
  297. ID: "kin_crustacean", Name: "Custacian",
  298. Short: "Beast protected by a tough shell",
  299. Long:
  300. `You might find it hard to inflict any damage to these well armoured beings.
  301. Their shells protect them against damage and allow them to live in the water
  302. and as well on the land.`,
  303. },
  304. Talents : Talents { Strength : +2, Toughness: +4,
  305. Intelligence: -5, },
  306. },
  307. { Entity: Entity {
  308. ID: "kin_insect", Name: "Insect",
  309. Short: "Beast with articulated legs and bodies.",
  310. Long:
  311. `The climate of Earth hs shifted dramaticaly over the last 60000 years,
  312. and as a result, larger creepy crawlers became more successful.
  313. `,
  314. },
  315. Talents : Talents { Strength : +2, Toughness: +4, Intelligence: -5, },
  316. },
  317. { Entity: Entity {
  318. ID: "kin_aquatic", Name: "beast",
  319. Short: "Aquatic beast. ",
  320. Long:
  321. `Whether in the rivers or the deep seas, these soft bodies creatures
  322. are often toxic and quite dangerous.`,
  323. },
  324. Talents : Talents { Strength : +2, Dexterity: +2, Intelligence: -5, },
  325. },
  326. { Entity: Entity {
  327. ID: "kin_corrupted", Name: "corrupted",
  328. Short: "Beast corupted by Omen. ",
  329. Long:
  330. `Some animals became corrupted by Omen. As a result, they became much stronger
  331. and more resillient. Fortunately, the Omen is weak against certain Numen arts.
  332. Beware, their attacks might be contageous...`,
  333. },
  334. Talents : Talents { Strength : +4, Toughness: +4,
  335. Agility : +1, Intelligence: -3, Wisdom: -5 },
  336. },
  337. { Entity: Entity {
  338. ID: "kin_deceased", Name: "Deceased",
  339. Short: "Deceased biological being animated by Omen. ",
  340. Long:
  341. `Some living beings become corrupted by Omen to the point that they remain
  342. animated even after their biological bodies have already stopped functioning.
  343. Such beings are termed the Deceased. They are resillient, strong and cunning.
  344. Fortunately, the Omen is weak against certain Numen arts. But beware, their
  345. attacks might be contageous...
  346. `,
  347. },
  348. Talents : Talents { Strength : +2, Toughness: +2,
  349. Agility : +1, Intelligence: -1, Wisdom: -7 },
  350. },
  351. }
  352. /* All jobs of WOE
  353. * agent officer guardian
  354. * worker brawler builder
  355. * hunter gunsman rogue
  356. * explorer ranger rebel
  357. * tinker engineer wrecker
  358. * homemaker musician trader
  359. * scholar scientist hacker
  360. * medic cleric artist
  361. * esper dilettante (not playable) Danger
  362. *
  363. *
  364. * hunter scholar esper worker medic agent officer cleric guardian ranger wrecker engineer tinker scientist
  365. *
  366. *
  367. *
  368. Officer STR + 1
  369. Worker TOU + 1
  370. Engineer DEX + 1
  371. Hunter AGI + 1
  372. Scholar INT + 1
  373. Doctor WIS +1
  374. Cleric CHA + 1
  375. *
  376. *
  377. */
  378. var JobList = [] Job {
  379. { Entity: Entity {
  380. ID: "job_hunter", Name: "Hunter",
  381. Short: "Hunter who chases beasts and mavericks.",
  382. Long:
  383. `Hunters protect human settlements from Beasts and Mavericks, and try to keep their numbers down.
  384. `,
  385. },
  386. Talents : Talents { Dexterity: +2 },
  387. Skills : map[ID] int{ "skill_guns": 10, },
  388. Playable: true,
  389. },
  390. }
  391. type LabeledPointer struct {
  392. ID ID
  393. labeled * Labeled
  394. }
  395. type GenderPointer struct {
  396. ID ID
  397. gender * Gender
  398. }
  399. //}
  400. /* Vital statistic of a Being. */
  401. type Vital struct {
  402. Now int `xml:"N,attr"`
  403. Max int `xml:"X,attr"`
  404. }
  405. /* Report a vital statistic as a Now/Max string */
  406. func (me * Vital) ToNowMax() string {
  407. return fmt.Sprintf("%4d/%4d", me.Now , me.Max)
  408. }
  409. // alias of the above, since I'm lazy at times
  410. func (me * Vital) TNM() string {
  411. return me.ToNowMax()
  412. }
  413. /* Report a vital statistic as a rounded percentage */
  414. func (me * Vital) ToPercentage() string {
  415. percentage := (me.Now * 100) / me.Max
  416. return fmt.Sprintf("%d", percentage)
  417. }
  418. /* Report a vital statistic as a bar of characters */
  419. func (me * Vital) ToBar(full string, empty string, length int) string {
  420. numfull := (me.Now * length) / me.Max
  421. numempty := length - numfull
  422. return strings.Repeat(empty, numempty) + strings.Repeat(full, numfull)
  423. }
  424. type Talents struct {
  425. Strength int `xml:"Talents>STR,omitempty"`
  426. Toughness int `xml:"Talents>TOU,omitempty"`
  427. Agility int `xml:"Talents>AGI,omitempty"`
  428. Dexterity int `xml:"Talents>DEX,omitempty"`
  429. Intelligence int `xml:"Talents>INT,omitempty"`
  430. Wisdom int `xml:"Talents>WIS,omitempty"`
  431. Charisma int `xml:"Talents>CHA,omitempty"`
  432. Emotion int `xml:"Talents>EMO,omitempty"`
  433. }
  434. type Vitals struct {
  435. HP Vital
  436. MP Vital
  437. JP Vital
  438. LP Vital
  439. }
  440. type EquipmentValues struct {
  441. Offense int
  442. Protection int
  443. Block int
  444. Rapidity int
  445. Yield int
  446. }
  447. type Being struct {
  448. Entity
  449. // Essentials
  450. Gender
  451. Kin
  452. Job
  453. Level int
  454. // A being has talents.
  455. Talents
  456. // A being has vitals
  457. Vitals
  458. // A being has Equipment values
  459. EquipmentValues
  460. // A being has aptitudes
  461. Aptitudes
  462. // Skills array
  463. // Skills []Skill
  464. // Arts array
  465. // Arts []Art
  466. // Affects array
  467. // Affects []Affect
  468. // Equipment
  469. // Equipment
  470. // Inventory
  471. Inventory Inventory
  472. // Location pointer
  473. room * Room
  474. }
  475. // Derived stats
  476. func (me *Being) Force() int {
  477. return (me.Strength * 2 + me.Wisdom) / 3
  478. }
  479. func (me *Being) Vitality() int {
  480. return (me.Toughness * 2 + me.Charisma) / 3
  481. }
  482. func (me *Being) Quickness() int {
  483. return (me.Agility * 2 + me.Intelligence) / 3
  484. }
  485. func (me * Being) Knack() int {
  486. return (me.Dexterity * 2 + me.Emotion) / 3
  487. }
  488. func (me * Being) Understanding() int {
  489. return (me.Intelligence * 2 + me.Toughness) / 3
  490. }
  491. func (me * Being) Grace() int {
  492. return (me.Charisma * 2 + me.Agility) / 3
  493. }
  494. func (me * Being) Zeal() int {
  495. return (me.Wisdom * 2 + me.Strength) / 3
  496. }
  497. func (me * Being) Numen() int {
  498. return (me.Emotion * 2 + me.Dexterity) / 3
  499. }
  500. // Generates a prompt for use with the being/character
  501. func (me * Being) ToPrompt() string {
  502. if me.Emotion > 0 {
  503. return fmt.Sprintf("HP:%s MP:%s JP:%s LP:%s", me.HP.TNM(), me.MP.TNM(), me.JP.TNM, me.LP.TNM())
  504. } else {
  505. return fmt.Sprintf("HP:%s MP:%s LP:%s", me.HP.TNM(), me.MP.TNM(), me.LP.TNM())
  506. }
  507. }
  508. // Generates an overview of the essentials of the being as a string.
  509. func (me * Being) ToEssentials() string {
  510. return fmt.Sprintf("%s lvl %d %s %s %s", me.Name, me.Level, me.Gender.Name, me.Kin.Name, me.Job.Name)
  511. }
  512. // Generates an overview of the physical talents of the being as a string.
  513. func (me * Being) ToBodyTalents() string {
  514. return fmt.Sprintf("STR: %3d TOU: %3d AGI: %3d DEX: %3d", me.Strength, me.Toughness, me.Agility, me.Dexterity)
  515. }
  516. // Generates an overview of the mental talents of the being as a string.
  517. func (me * Being) ToMindTalents() string {
  518. return fmt.Sprintf("INT: %3d WIS: %3d CHA: %3d EMO: %3d", me.Intelligence, me.Wisdom, me.Charisma, me.Emotion)
  519. }
  520. // Generates an overview of the equipment values of the being as a string.
  521. func (me * Being) ToEquipmentValues() string {
  522. return fmt.Sprintf("OFF: %3d PRO: %3d BLO: %3d RAP: %3d YIE: %3d", me.Offense, me.Protection, me.Block, me.Rapidity, me.Yield)
  523. }
  524. // Generates an overview of the status of the being as a string.
  525. func (me * Being) ToStatus() string {
  526. status := me.ToEssentials()
  527. status += "\n" + me.ToBodyTalents();
  528. status += "\n" + me.ToMindTalents();
  529. status += "\n" + me.ToEquipmentValues();
  530. status += "\n" + me.ToPrompt();
  531. status += "\n"
  532. return status
  533. }
  534. func (me *Being) Type() string {
  535. return "being"
  536. }
  537. func (me *Being) Save(datadir string) {
  538. SaveSavable(datadir, me)
  539. }
  540. func LoadBeing(datadir string, nameid string) * Being {
  541. res, _ := LoadLoadable(datadir, nameid, new(Being)).(*Being)
  542. return res
  543. }