rpg_stat/stats.rs
1/*!
2# Stats
3
4This module offers a few options.
5
6### FLTK
7
8The use of `fltk-form` allows easy integration into a GUI toolkit via the FLTK specific `Stats`
9
10### Premade traits to add to your own struct
11
12```
13use rpg_stat::stats::Basic as Stats;
14use rpg_stat::stats::BasicPremade as Premade;
15
16struct MyStruct {
17 stats:Stats<f64>,
18 // whatever else you need
19}
20// now you can get the stats `hp` via `my_struct.hp()`, etc..
21impl Premade<f64> for MyStruct {
22 fn stat(&self) -> Stats<f64> {
23 self.stats
24 }
25 fn set_hp(&mut self, amount:f64) {
26 self.stats.hp = amount;
27 }
28 fn set_mp(&mut self, amount:f64) {
29 self.stats.mp = amount;
30 }
31 fn set_xp(&mut self, amount:f64) {
32 self.stats.xp = amount;
33 }
34 fn set_hp_max(&mut self, amount:f64) {
35 self.stats.hp_max = amount;
36 }
37 fn set_mp_max(&mut self, amount:f64) {
38 self.stats.mp_max = amount;
39 }
40 fn set_xp_next(&mut self, amount:f64) {
41 self.stats.xp_next = amount;
42 }
43 fn set_gp(&mut self, amount:f64) {
44 self.stats.gp = amount;
45 }
46
47}
48```
49
50And for FLTK premade f64:
51
52```
53use rpg_stat::stats::Stats;
54use rpg_stat::stats::Premade;
55
56struct MyStruct {
57 stats:Stats,
58 // whatever else you need
59}
60// now you can get the stats `hp` via `my_struct.hp()`, etc..
61impl Premade for MyStruct {
62 fn stat(&self) -> Stats {
63 self.stats
64 }
65 fn set_hp(&mut self, amount:f64) {
66 self.stats.hp = amount;
67 }
68 fn set_mp(&mut self, amount:f64) {
69 self.stats.mp = amount;
70 }
71 fn set_xp(&mut self, amount:f64) {
72 self.stats.xp = amount;
73 }
74 fn set_hp_max(&mut self, amount:f64) {
75 self.stats.hp_max = amount;
76 }
77 fn set_mp_max(&mut self, amount:f64) {
78 self.stats.mp_max = amount;
79 }
80 fn set_xp_next(&mut self, amount:f64) {
81 self.stats.xp_next = amount;
82 }
83 fn set_gp(&mut self, amount:f64) {
84 self.stats.gp = amount;
85 }
86 fn set_atk(&mut self, amount:f64) {
87 self.stats.atk = amount;
88 }
89 fn set_def(&mut self, amount:f64) {
90 self.stats.def = amount;
91 }
92 fn set_m_atk(&mut self, amount:f64) {
93 self.stats.m_atk = amount;
94 }
95 fn set_m_def(&mut self, amount:f64) {
96 self.stats.m_def = amount;
97 }
98 fn set_level(&mut self, amount:f64) {
99 self.stats.level = amount;
100 }
101 fn set_speed(&mut self, amount:f64) {
102 self.stats.speed = amount;
103 }
104}
105
106```
107
108# Structure
109This contains the basic structures for the RPG statistics library
110
111## `Basic` contains only the most needed for a generic game
112
113### id
114this can be used in any way to ID the stats
115
116### xp
117The experience points the stats currently hold
118
119### xp_next
120the amount needed to reach the next level
121
122### level
123the level of proficiency of the stats
124
125### gp
126the currency the stats currently have
127
128### hp
129the current health in the stats
130
131### mp
132the current mana in the stats
133
134### hp_max
135the total health possible
136
137### mp_max
138the total mana possible
139
140### speed
141the speed the stats move at
142
143## `Normal` includes a few more for the generic RPG battle system as well as everything in `Basic`
144
145### atk
146used specifically in battle as the attack variable
147
148### def
149used specifically in battle as the defense variable
150
151### m_atk
152used specifically in battle as the mana attack variable
153
154### m_def
155used specifically in battle as the mana defense variable
156
157## `Advanced` contains the finer details seen in tabletop RPG stats as well as everything in `Normal` and `Basic`
158
159### agility
160
161Fight mechanics:
162 * Increases dodge
163 * Increases accuracy
164
165Story mechanics:
166 * Increases success rate
167 * Increases options
168 * Decreases confrontation rate
169
170### strength
171
172Fight mechanics:
173 * Increases attack
174 * Increases defense
175
176Story mechanics:
177 * Increases confrontations
178 * Increases special item finds
179 * Increases success rate
180
181### dexterity
182
183Fight mechanics:
184 * Increases accuracy
185
186Story mechanics:
187 * Increases options
188 * Decreases confrontation rate
189
190### constitution
191
192Fight mechanics:
193 * Increases dodge
194 * Increases defense
195
196Story mechanics:
197 * Increases success rate
198 * Decreases confrontation rate
199
200### intelligence
201
202Fight mechanics:
203 * Increases accuracy
204
205Story mechanics:
206 * Increases confrontations
207 * Increases special item finds
208 * Increases success rate
209
210### charisma
211
212Fight mechanics:
213 * Increases dodge
214
215Story mechanics:
216 * Increases options
217 * Increases reward
218 * Decreases confrontation rate
219
220### wisdom
221
222Fight mechanics:
223 * Increases leveling
224
225Story mechanics:
226 * Increases reward
227 * Decreases confrontation rate
228
229### age
230
231Age is really to allow things to grow through a Stage
232
233Fight mechanics:
234 * Items, Weapons, Armor, etc may be formulated for specific age ranges and prevent users who are too young or old to use them.
235
236Story mechanics:
237 * Age could potentially influence story mechanics, being to young to leave an area would promote grinding.
238
239 */
240use std::default::Default;
241use serde::{Deserialize, Serialize};
242extern crate num;
243
244use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Rem, RemAssign, Sub, SubAssign};
245use std::fmt::Debug;
246
247#[cfg(feature = "fltkform")]
248use fltk::{prelude::*, *};
249#[cfg(feature = "fltkform")]
250use fltk_form_derive::*;
251#[cfg(feature = "fltkform")]
252use fltk_form::FltkForm;
253
254
255use crate::random::*;
256use crate::equation::Math;
257
258pub trait Functions <T:Copy
259 + Default
260 + Debug
261 + AddAssign
262 + Add<Output = T>
263 + Div<Output = T>
264 + DivAssign
265 + Mul<Output = T>
266 + MulAssign
267 + Neg<Output = T>
268 + Rem<Output = T>
269 + RemAssign
270 + Sub<Output = T>
271 + SubAssign
272 + std::cmp::PartialOrd
273 + num::NumCast> {
274 type Statistics;
275 fn damage(&self);
276}
277/*
278# Builder
279
280The builder trait is how I create `rpg_stat::stats::{Basic,Normal,Advance}` from enums
281
282*/
283pub trait Builder <T:Copy
284 + Default
285 + Debug
286 + AddAssign
287 + Add<Output = T>
288 + Div<Output = T>
289 + DivAssign
290 + Mul<Output = T>
291 + MulAssign
292 + Neg<Output = T>
293 + Rem<Output = T>
294 + RemAssign
295 + Sub<Output = T>
296 + SubAssign
297 + std::cmp::PartialOrd
298 + num::NumCast> {
299 /// Build a `Basic` stat
300 fn build_basic(&self, id:T, level:T) -> Basic<T>;
301 // Build a `Normal` stat
302 fn build_normal(&self, id:T, level:T) -> Normal<T>;
303 // Build an `Advanced` stat
304 fn build_advanced(&self, id:T, level:T) -> Advanced<T>;
305}
306
307/*
308Premade trait for Basic Stat
309You simply define the function `stat()` to return the `Basic<T>` associated with your code.
310*/
311pub trait BasicPremade<T:Copy
312 + Default
313 + Debug
314 + AddAssign
315 + Add<Output = T>
316 + Div<Output = T>
317 + DivAssign
318 + Mul<Output = T>
319 + MulAssign
320 + Neg<Output = T>
321 + Rem<Output = T>
322 + RemAssign
323 + Sub<Output = T>
324 + SubAssign
325 + std::cmp::PartialOrd
326 + num::NumCast> {
327 /// # Function you need to imlement
328 /// stat returns the `Basic<T>` you created
329 fn stat(&self) -> Basic<T>;
330 /// # Function you need to imlement
331 /// Set the `Basic<T>` Health Points
332 fn set_hp(&mut self, amount:T);
333 /// # Function you need to imlement
334 /// Set the `Basic<T>` Mana Points
335 fn set_mp(&mut self, amount:T);
336 /// # Function you need to imlement
337 /// Set the `Basic<T>` Experience Points
338 fn set_xp(&mut self, amount:T);
339 /// # Function you need to imlement
340 /// Set the `Basic<T>` Max Health Points
341 fn set_hp_max(&mut self, amount:T);
342 /// # Function you need to imlement
343 /// Set the `Basic<T>` Max Mana Points
344 fn set_mp_max(&mut self, amount:T);
345 /// # Function you need to imlement
346 /// Set the `Basic<T>` Next Experience Points
347 fn set_xp_next(&mut self, amount:T);
348 /// # Function you need to imlement
349 /// Set the `Basic<T>` Gold Points
350 fn set_gp(&mut self, amount:T);
351 /// Return the `Basic<T>` id number
352
353// PREMADE FUNCTIONS
354 fn id(&self) -> T {
355 self.stat().id
356 }
357 /// Return the `Basic<T>` Health Points
358 fn hp(&self) -> T {
359 self.stat().hp
360 }
361 /// Return the `Basic<T>` Mana Points
362 fn mp(&self) -> T {
363 self.stat().mp
364 }
365 /// Return the `Basic<T>` Experience Points
366 fn xp(&self) -> T {
367 self.stat().xp
368 }
369 /// Return the `Basic<T>` Max Health Points
370 fn hp_max(&self) -> T {
371 self.stat().hp_max
372 }
373 /// Return the `Basic<T>` Max Mana Points
374 fn mp_max(&self) -> T {
375 self.stat().mp_max
376 }
377 /// Return the `Basic<T>` Next Experience Points
378 fn xp_next(&self) -> T {
379 self.stat().xp_next
380 }
381 /// Return the `Basic<T>` Level
382 fn level(&self) -> T {
383 self.stat().level
384 }
385 /// Return the `Basic<T>` Speed
386 fn speed(&self) -> T {
387 self.stat().level
388 }
389 /// Return the `Basic<T>` Gold Points
390 fn gp(&self) -> T {
391 self.stat().gp
392 }
393 /// Damage the character by an amount
394 fn damage(&mut self, amount:T) {
395 let mut val = self.hp();
396 val -= amount;
397 let none = num::cast(0).unwrap();
398 if val < none {
399 val = none;
400 }
401 self.set_hp(val)
402 }
403 /// Add health to character but not beyond their Max Healh Points
404 fn heal(&mut self, amount:T) {
405 let mut val = self.hp();
406 val += amount;
407 let max = self.hp_max();
408 if val > max {
409 val = max;
410 }
411 self.set_hp(val)
412 }
413}
414
415/*
416# The Basic HP/MP/XP stat model
417
418This basic model of stats is easy to work with for beginners, but powerful enough to be used by the most experienced.
419*/
420
421#[derive( Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
422pub struct Basic<T:Copy
423 + Default
424 + Debug
425 + AddAssign
426 + Add<Output = T>
427 + Div<Output = T>
428 + DivAssign
429 + Mul<Output = T>
430 + MulAssign
431 + Neg<Output = T>
432 + Rem<Output = T>
433 + RemAssign
434 + Sub<Output = T>
435 + SubAssign
436 + std::cmp::PartialOrd
437 + num::NumCast> {
438 /// Identification Number
439 pub id:T,
440 /// Experience Points
441 pub xp:T,
442 /// Health Points
443 pub hp:T,
444 /// Mana Points
445 pub mp:T,
446 /// Experience Points multiplier for next level
447 pub xp_next:T,
448 /// Max Health Points
449 pub hp_max:T,
450 /// Max Mana Points
451 pub mp_max:T,
452 /// Current Level
453 pub level:T,
454 /// The speed
455 pub speed:T,
456 /// your currency points
457 pub gp:T,
458}
459impl<T:Copy
460 + Default
461 + Debug
462 + AddAssign
463 + Add<Output = T>
464 + Div<Output = T>
465 + DivAssign
466 + Mul<Output = T>
467 + MulAssign
468 + Neg<Output = T>
469 + Rem<Output = T>
470 + RemAssign
471 + Sub<Output = T>
472 + SubAssign
473 + std::cmp::PartialOrd
474 + num::NumCast> Basic<T> {
475
476 /// make empty stats
477 pub fn empty() -> Self where Self:Sized {
478 Basic {
479 id:Default::default(),
480 xp:Default::default(),
481 xp_next:Default::default(),
482 mp:Default::default(),
483 hp:Default::default(),
484 mp_max:Default::default(),
485 hp_max:Default::default(),
486 level:Default::default(),
487 speed:Default::default(),
488 gp:Default::default(),
489 }
490 }
491 /// People like new
492 #[allow(unused)]
493 pub fn new() -> Self {
494 Self::empty()
495 }
496 #[allow(unused)]
497 /// Get the next amount of XP needed to level up
498 pub fn next(&self) -> T {
499 self.level * self.xp_next
500 }
501 #[allow(unused)]
502 /// a vector of stats used to get the standard deviation
503 pub fn stats_vec(&self) -> Vec<T>{
504 vec![
505 self.hp_max,
506 self.mp_max,
507 self.speed,
508 ]
509 }
510
511 #[allow(unused)]
512 /// This function levels up our stats
513 pub fn level_up(&mut self) -> bool {
514 if self.xp > self.next() {
515 let stats_vec:Vec<T> = self.stats_vec();
516 let mut num:T = Math::population_standard_deviation(stats_vec);
517 let one:T = num::cast::<u32, T>(1).unwrap();
518 if num < one {
519 num = one;
520 }
521 num *= self.level;
522 self.level += num;
523 self.mp_max += num;
524 self.hp_max += num;
525 self.speed += num;
526 return true;
527 }
528 false
529 }
530}
531impl<T:Copy
532 + Default
533 + Debug
534 + AddAssign
535 + Add<Output = T>
536 + Div<Output = T>
537 + DivAssign
538 + Mul<Output = T>
539 + MulAssign
540 + Neg<Output = T>
541 + Rem<Output = T>
542 + RemAssign
543 + Sub<Output = T>
544 + SubAssign
545 + std::cmp::PartialOrd
546 + num::NumCast> Default for Basic<T> {
547 /// Default to empty
548 fn default() -> Self where Self:Sized {
549 Self::empty()
550 }
551}
552
553/*
554Premade trait for Normal Stat
555You simply define the function `stat()` to return the `Normal<T>` associated with your code.
556*/
557pub trait NormalPremade<T:Copy
558 + Default
559 + Debug
560 + AddAssign
561 + Add<Output = T>
562 + Div<Output = T>
563 + DivAssign
564 + Mul<Output = T>
565 + MulAssign
566 + Neg<Output = T>
567 + Rem<Output = T>
568 + RemAssign
569 + Sub<Output = T>
570 + SubAssign
571 + std::cmp::PartialOrd
572 + num::NumCast> {
573 /// # Function you need to imlement
574 /// stat returns the `Normal<T>` you created
575 fn stat(&self) -> Normal<T>;
576 /// # Function you need to imlement
577 /// Set the `Normal<T>` Health Points
578 fn set_hp(&mut self, amount:T);
579 /// # Function you need to imlement
580 /// Set the `Normal<T>` Mana Points
581 fn set_mp(&mut self, amount:T);
582 /// # Function you need to imlement
583 /// Set the `Normal<T>` Experience Points
584 fn set_xp(&mut self, amount:T);
585 /// # Function you need to imlement
586 /// Set the `Normal<T>` Max Health Points
587 fn set_hp_max(&mut self, amount:T);
588 /// # Function you need to imlement
589 /// Set the `Normal<T>` Max Mana Points
590 fn set_mp_max(&mut self, amount:T);
591 /// # Function you need to imlement
592 /// Set the `Normal<T>` Next Experience Points
593 fn set_xp_next(&mut self, amount:T);
594 /// # Function you need to imlement
595 /// Set the `Normal<T>` Gold Points
596 fn set_gp(&mut self, amount:T);
597 /// # Function you need to imlement
598 /// Set the `Normal<T>` Attack Points
599 fn set_atk(&mut self, amount:T);
600 /// # Function you need to imlement
601 /// Set the `Normal<T>` Defense Points
602 fn set_def(&mut self, amount:T);
603 /// # Function you need to imlement
604 /// Set the `Normal<T>` Mana Attack Points
605 fn set_m_atk(&mut self, amount:T);
606 /// # Function you need to imlement
607 /// Set the `Normal<T>` Mana Defense Points
608 fn set_m_def(&mut self, amount:T);
609
610// PREMADE FUNCTIONS
611 /// Return the `Normal<T>` id number
612 fn id(&self) -> T {
613 self.stat().id
614 }
615 /// Return the `Normal<T>` Health Points
616 fn hp(&self) -> T {
617 self.stat().hp
618 }
619 /// Return the `Normal<T>` Mana Points
620 fn mp(&self) -> T {
621 self.stat().mp
622 }
623 /// Return the `Normal<T>` Experience Points
624 fn xp(&self) -> T {
625 self.stat().xp
626 }
627 /// Return the `Normal<T>` Max Health Points
628 fn hp_max(&self) -> T {
629 self.stat().hp_max
630 }
631 /// Return the `Normal<T>` Max Mana Points
632 fn mp_max(&self) -> T {
633 self.stat().mp_max
634 }
635 /// Return the `Normal<T>` Next Experience Points
636 fn xp_next(&self) -> T {
637 self.stat().xp_next
638 }
639 /// Return the `Normal<T>` Level
640 fn level(&self) -> T {
641 self.stat().level
642 }
643 /// Return the `Normal<T>` Speed
644 fn speed(&self) -> T {
645 self.stat().level
646 }
647 /// Return the `Normal<T>` Gold Points
648 fn gp(&self) -> T {
649 self.stat().gp
650 }
651 /// Return the `Normal<T>` Attack Points
652 fn atk(&self) -> T {
653 self.stat().atk
654 }
655 /// Return the `Normal<T>` Defense Points
656 fn def(&self) -> T {
657 self.stat().def
658 }
659 /// Return the `Normal<T>` Mana Attack Points
660 fn m_atk(&self) -> T {
661 self.stat().m_atk
662 }
663 /// Return the `Normal<T>` Mana Defense Points
664 fn m_def(&self) -> T {
665 self.stat().m_def
666 }
667
668 /// Damage the character by an amount
669 fn damage(&mut self, amount:T) {
670 let mut val = self.hp();
671 val -= amount;
672 let none = num::cast(0).unwrap();
673 if val < none {
674 val = none;
675 }
676 self.set_hp(val)
677 }
678 /// Add health to character but not beyond their Max Healh Points
679 fn heal(&mut self, amount:T) {
680 let mut val = self.hp();
681 val += amount;
682 let max = self.hp_max();
683 if val > max {
684 val = max;
685 }
686 self.set_hp(val)
687 }
688 /// Stable attack forumla
689 /// [attack*(100/(100+defense))](https://rpg.fandom.com/wiki/Damage_Formula)
690 fn attack_stable(&self, other:Normal<T>) -> T {
691 let hundred = num::cast(100).unwrap();
692 let val = self.atk();
693 let def = other.def + hundred;
694 let res = hundred / def;
695 val * res
696 }
697 /// Scalable attack forumla
698 /// [damage = att * att / (att + def)](https://gamedev.stackexchange.com/questions/129319/rpg-formula-attack-and-defense)
699 fn attack(&self, other:Normal<T>) -> T {
700 let val = self.atk();
701 let mut res = val * val;
702 let def = other.def + val;
703 res /= def;
704 res
705 }
706}
707/*
708# The Normal
709
710This model provides fine tuning of attack and defense without needing all the fine tuning of a full stat sheet
711*/
712#[derive( Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
713pub struct Normal<T:Copy
714 + Default
715 + AddAssign
716 + Add<Output = T>
717 + Div<Output = T>
718 + DivAssign
719 + Mul<Output = T>
720 + MulAssign
721 + Neg<Output = T>
722 + Rem<Output = T>
723 + RemAssign
724 + Sub<Output = T>
725 + SubAssign
726 + std::cmp::PartialOrd
727 + num::NumCast> {
728 /// Identification Number
729 pub id:T,
730 // Name
731 //pub name:str,
732 /// Experience Points
733 pub xp:T,
734 /// Health Points
735 pub hp:T,
736 /// Mana Points
737 pub mp:T,
738 /// Experience Points multiplier for next level
739 pub xp_next:T,
740 /// Max Health Points
741 pub hp_max:T,
742 /// Max Mana Points
743 pub mp_max:T,
744 /// Current Level
745 pub level:T,
746 /// The speed
747 pub speed:T,
748 /// your currency points
749 pub gp:T,
750 /// Attack
751 pub atk:T,
752 /// Defense
753 pub def:T,
754 /// Mana Attack
755 pub m_atk:T,
756 /// Mana Defense
757 pub m_def:T,
758
759}
760impl<T:Copy
761 + Default
762 + AddAssign
763 + Add<Output = T>
764 + Div<Output = T>
765 + DivAssign
766 + Mul<Output = T>
767 + MulAssign
768 + Neg<Output = T>
769 + Rem<Output = T>
770 + RemAssign
771 + Sub<Output = T>
772 + SubAssign
773 + std::cmp::PartialOrd
774 + num::NumCast> Normal<T> {
775
776 /// make empty stats
777 pub fn empty<U:Default>() -> Self {
778 Normal {
779 //name: "Ferris",
780 id:Default::default(),
781 xp:Default::default(),
782 xp_next:Default::default(),
783 mp:Default::default(),
784 hp:Default::default(),
785 mp_max:Default::default(),
786 hp_max:Default::default(),
787 level:Default::default(),
788 speed:Default::default(),
789 gp:Default::default(),
790 atk:Default::default(),
791 def:Default::default(),
792 m_atk:Default::default(),
793 m_def:Default::default(),
794 }
795 }/// People like new
796 #[allow(unused)]
797 pub fn new() -> Self {
798 Self::empty::<T>()
799 }
800 #[allow(unused)]
801 /// Get the next amount of XP needed to level up
802 pub fn next(&self) -> T {
803 self.level * self.xp_next
804 }
805 #[allow(unused)]
806 /// a vector of stats used to get the standard deviation
807 pub fn stats_vec(&self) -> Vec<T>{
808 vec![
809 self.hp_max,
810 self.mp_max,
811 self.speed,
812 self.atk,
813 self.def,
814 self.m_atk,
815 self.m_def,
816 ]
817 }
818
819 #[allow(unused)]
820 /// This function levels up our stats
821 pub fn level_up(&mut self) -> bool {
822 if self.xp > self.next() {
823 let stats_vec:Vec<T> = self.stats_vec();
824 let mut num:T = Math::population_standard_deviation(stats_vec);
825 let one:T = num::cast::<u32, T>(1).unwrap();
826 if num < one {
827 num = one;
828 }
829 num *= self.level;
830 self.level += num;
831 self.mp_max += num;
832 self.hp_max += num;
833 self.speed += num;
834 self.atk += num;
835 self.def += num;
836 self.m_atk += num;
837 self.m_def += num;
838 return true;
839 }
840 false
841 }
842}
843
844impl<T:Copy
845 + Default
846 + AddAssign
847 + Add<Output = T>
848 + Div<Output = T>
849 + DivAssign
850 + Mul<Output = T>
851 + MulAssign
852 + Neg<Output = T>
853 + Rem<Output = T>
854 + RemAssign
855 + Sub<Output = T>
856 + SubAssign
857 + std::cmp::PartialOrd
858 + num::NumCast> Default for Normal<T> {
859 /// Default to empty
860 fn default() -> Self {
861 Self::empty::<T>()
862 }
863}
864
865/*
866Premade trait for Advanced Stat
867You simply define the function `stat()` to return the `Advanced<T>` associated with your code.
868*/
869pub trait AdvancedPremade<T:Copy
870 + Default
871 + Debug
872 + AddAssign
873 + Add<Output = T>
874 + Div<Output = T>
875 + DivAssign
876 + Mul<Output = T>
877 + MulAssign
878 + Neg<Output = T>
879 + Rem<Output = T>
880 + RemAssign
881 + Sub<Output = T>
882 + SubAssign
883 + std::cmp::PartialOrd
884 + num::NumCast> {
885 /// # Function you need to imlement
886 /// stat returns the `Advanced<T>` you created
887 fn stat(&self) -> Advanced<T>;
888 /// # Function you need to imlement
889 /// Set the `Advanced<T>` Health Points
890 fn set_hp(&mut self, amount:T);
891 /// # Function you need to imlement
892 /// Set the `Advanced<T>` Mana Points
893 fn set_mp(&mut self, amount:T);
894 /// # Function you need to imlement
895 /// Set the `Advanced<T>` Experience Points
896 fn set_xp(&mut self, amount:T);
897 /// # Function you need to imlement
898 /// Set the `Advanced<T>` Max Health Points
899 fn set_hp_max(&mut self, amount:T);
900 /// # Function you need to imlement
901 /// Set the `Advanced<T>` Max Mana Points
902 fn set_mp_max(&mut self, amount:T);
903 /// # Function you need to imlement
904 /// Set the `Advanced<T>` Next Experience Points
905 fn set_xp_next(&mut self, amount:T);
906 /// # Function you need to imlement
907 /// Set the `Advanced<T>` Gold Points
908 fn set_gp(&mut self, amount:T);
909 /// # Function you need to imlement
910 /// Set the `Advanced<T>` Attack Points
911 fn set_atk(&mut self, amount:T);
912 /// # Function you need to imlement
913 /// Set the `Advanced<T>` Defense Points
914 fn set_def(&mut self, amount:T);
915 /// # Function you need to imlement
916 /// Set the `Advanced<T>` Mana Attack Points
917 fn set_m_atk(&mut self, amount:T);
918 /// # Function you need to imlement
919 /// Set the `Advanced<T>` Mana Defense Points
920 fn set_m_def(&mut self, amount:T);
921
922// PREMADE FUNCTIONS
923 /// Get the id number
924 fn id(&self) -> T {
925 self.stat().id
926 }
927 /// Get the Health Points
928 fn hp(&self) -> T {
929 self.stat().hp
930 }
931 /// Get the Mana Points
932 fn mp(&self) -> T {
933 self.stat().mp
934 }
935 /// Get the Experience Points
936 fn xp(&self) -> T {
937 self.stat().xp
938 }
939 /// Get the Max Health Points
940 fn hp_max(&self) -> T {
941 self.stat().hp_max
942 }
943 /// Get the Max Mana Points
944 fn mp_max(&self) -> T {
945 self.stat().mp_max
946 }
947 /// Get the Experience Points
948 fn xp_next(&self) -> T {
949 self.stat().xp_next
950 }
951 /// Get the Current Level
952 fn level(&self) -> T {
953 self.stat().level
954 }
955 /// Get the Speed
956 fn speed(&self) -> T {
957 self.stat().level
958 }
959 /// Get the Attack Points
960 fn atk(&self) -> T {
961 self.stat().atk
962 }
963 /// Get the Defense Points
964 fn def(&self) -> T {
965 self.stat().def
966 }
967 /// Get the Mana Attack Points
968 fn m_atk(&self) -> T {
969 self.stat().m_atk
970 }
971 /// Get the Mana Defense Points
972 fn m_def(&self) -> T {
973 self.stat().m_def
974 }
975 /// Get the Gold Points
976 fn gp(&self) -> T {
977 self.stat().gp
978 }
979 /// Get the agility Points
980 fn agi(&self) -> T {
981 self.stat().agility
982 }
983 /// Get the strength Points
984 fn str(&self) -> T {
985 self.stat().strength
986 }
987 /// Get the intelligence Points
988 fn int(&self) -> T {
989 self.stat().intelligence
990 }
991 /// Get the dexterity Points
992 fn dex(&self) -> T {
993 self.stat().dexterity
994 }
995 /// Get the constitution Points
996 fn con(&self) -> T {
997 self.stat().constitution
998 }
999 /// Get the charisma Points
1000 fn char(&self) -> T {
1001 self.stat().charisma
1002 }
1003 /// Get the wisdom Points
1004 fn wis(&self) -> T {
1005 self.stat().wisdom
1006 }
1007 /// Get the Age
1008 fn age(&self) -> T {
1009 self.stat().age
1010 }
1011 /// Damage the character by an amount
1012 fn damage(&mut self, amount:T) {
1013 let mut val = self.hp();
1014 val -= amount;
1015 let none = num::cast(0).unwrap();
1016 if val < none {
1017 val = none;
1018 }
1019 self.set_hp(val)
1020 }
1021 /// Add health to character but not beyond their Max Healh Points
1022 fn heal(&mut self, amount:T) {
1023 let mut val = self.hp();
1024 val += amount;
1025 let max = self.hp_max();
1026 if val > max {
1027 val = max;
1028 }
1029 self.set_hp(val)
1030 }
1031 // TODO taken from `Normal`
1032 /// Stable attack forumla
1033 /// [attack*(100/(100+defense))](https://rpg.fandom.com/wiki/Damage_Formula)
1034 fn attack_stable(&self, other:Advanced<T>) -> T {
1035 let hundred = num::cast(100).unwrap();
1036 let val = self.atk();
1037 let def = other.def + hundred;
1038 let res = hundred / def;
1039 val * res
1040 }
1041 /// Scalable attack forumla
1042 /// [damage = att * att / (att + def)](https://gamedev.stackexchange.com/questions/129319/rpg-formula-attack-and-defense)
1043 fn attack(&self, other:Advanced<T>) -> T {
1044 let val = self.atk();
1045 let mut res = val * val;
1046 let mut def = other.def;
1047 def += val;
1048 res /= def;
1049 res
1050 }
1051}
1052/*
1053# The Advanced stat model
1054The entire stat sheet for fine tuned algorithms using all the information possible!
1055*/
1056#[allow(unused)]
1057#[derive( Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
1058pub struct Advanced<T:Copy
1059 + Default
1060 + Debug
1061 + AddAssign
1062 + Add<Output = T>
1063 + Div<Output = T>
1064 + DivAssign
1065 + Mul<Output = T>
1066 + MulAssign
1067 + Neg<Output = T>
1068 + Rem<Output = T>
1069 + RemAssign
1070 + Sub<Output = T>
1071 + SubAssign
1072 + std::cmp::PartialOrd
1073 + num::NumCast> {
1074 /// Identification Number
1075 pub id:T,
1076 /// Experience Points
1077 pub xp:T,
1078 /// Health Points
1079 pub hp:T,
1080 /// Mana Points
1081 pub mp:T,
1082 /// Experience Points multiplier for next level
1083 pub xp_next:T,
1084 /// Max Health Points
1085 pub hp_max:T,
1086 /// Max Mana Points
1087 pub mp_max:T,
1088 /// Current Level
1089 pub level:T,
1090 /// The speed
1091 pub speed:T,
1092 /// your currency points
1093 pub gp:T,
1094 /// Attack
1095 pub atk:T,
1096 /// Defense
1097 pub def:T,
1098 /// Mana Attack
1099 pub m_atk:T,
1100 /// Mana Defense
1101 pub m_def:T,
1102 /// The agility Points
1103 pub agility:T,
1104 /// The strength Points
1105 pub strength:T,
1106 /// The dexterity Points
1107 pub dexterity:T,
1108 /// The constitution Points
1109 pub constitution:T,
1110 /// The intelligence Points
1111 pub intelligence:T,
1112 /// The charisma Points
1113 pub charisma:T,
1114 /// The wisdom Points
1115 pub wisdom:T,
1116 /// The current age
1117 pub age:T,
1118
1119}
1120impl<T:Copy
1121 + Default
1122 + Debug
1123 + AddAssign
1124 + Add<Output = T>
1125 + Div<Output = T>
1126 + DivAssign
1127 + Mul<Output = T>
1128 + MulAssign
1129 + Neg<Output = T>
1130 + Rem<Output = T>
1131 + RemAssign
1132 + Sub<Output = T>
1133 + SubAssign
1134 + std::cmp::PartialOrd
1135 + num::NumCast> Advanced<T> {
1136 /// make empty stats
1137 #[allow(unused)]
1138 pub fn empty<U:Default>() -> Self {
1139 Advanced {
1140 id:Default::default(),
1141 xp:Default::default(),
1142 xp_next:Default::default(),
1143 mp:Default::default(),
1144 hp:Default::default(),
1145 mp_max:Default::default(),
1146 hp_max:Default::default(),
1147 level:Default::default(),
1148 speed:Default::default(),
1149 gp:Default::default(),
1150 atk:Default::default(),
1151 def:Default::default(),
1152 m_atk:Default::default(),
1153 m_def:Default::default(),
1154 agility:Default::default(),
1155 strength:Default::default(),
1156 dexterity:Default::default(),
1157 constitution:Default::default(),
1158 intelligence:Default::default(),
1159 charisma:Default::default(),
1160 wisdom:Default::default(),
1161 age:Default::default(),
1162 }
1163 }
1164 /// People like new
1165 #[allow(unused)]
1166 pub fn new<U:Default>() -> Self {
1167 Self::empty::<U>()
1168 }
1169 #[allow(unused)]
1170 /// Get the next amount of XP needed to level up
1171 pub fn next(&self) -> T {
1172 self.level * self.xp_next
1173 }
1174 #[allow(unused)]
1175 /// a vector of stats used to get the standard deviation
1176 pub fn stats_vec(&self) -> Vec<T>{
1177 vec![
1178 self.hp_max,
1179 self.mp_max,
1180 self.speed,
1181 self.atk,
1182 self.def,
1183 self.m_atk,
1184 self.m_def,
1185 self.agility,
1186 self.strength,
1187 self.dexterity,
1188 self.constitution,
1189 self.intelligence,
1190 self.charisma,
1191 ]
1192 }
1193
1194 #[allow(unused)]
1195 /// This function levels up our stats
1196 pub fn level_up(&mut self) -> bool {
1197 if self.xp > self.next() {
1198 let stats_vec:Vec<T> = self.stats_vec();
1199 let mut value:T = Math::population_standard_deviation(stats_vec);
1200 self.level += value;
1201 self.mp_max += value;
1202 self.hp_max += value;
1203 self.speed += value;
1204 self.atk += value;
1205 self.def += value;
1206 self.m_atk += value;
1207 self.m_def += value;
1208 self.agility += value;
1209 self.strength += value;
1210 self.dexterity += value;
1211 self.constitution += value;
1212 self.intelligence += value;
1213 self.charisma += value;
1214 return true;
1215 }
1216 false
1217 }
1218}
1219impl<T:Copy
1220 + Default
1221 + Debug
1222 + AddAssign
1223 + Add<Output = T>
1224 + Div<Output = T>
1225 + DivAssign
1226 + Mul<Output = T>
1227 + MulAssign
1228 + Neg<Output = T>
1229 + Rem<Output = T>
1230 + RemAssign
1231 + Sub<Output = T>
1232 + SubAssign
1233 + std::cmp::PartialOrd
1234 + num::NumCast> Default for Advanced<T> {
1235 /// Default to empty
1236 fn default() -> Self {
1237 Self::empty::<T>()
1238 }
1239}
1240
1241/*
1242# The FLTK Stats
1243This is designed to be used with FLTK, but can be used without FLTK
1244*/
1245#[derive( Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
1246#[cfg_attr(feature = "fltkform", derive(FltkForm))]
1247pub struct Stats {
1248 /// Identification Number
1249 pub id:f64,
1250 /// Experience Points
1251 pub xp:f64,
1252 /// Health Points
1253 pub hp:f64,
1254 /// Mana Points
1255 pub mp:f64,
1256 /// Experience Points multiplier for next level
1257 pub xp_next:f64,
1258 /// Max Health Points
1259 pub hp_max:f64,
1260 /// Max Mana Points
1261 pub mp_max:f64,
1262 /// Current Level
1263 pub level:f64,
1264 /// The speed
1265 pub speed:f64,
1266 /// your currency points
1267 pub gp:f64,
1268 /// Attack
1269 pub atk:f64,
1270 /// Defense
1271 pub def:f64,
1272 /// Mana Attack
1273 pub m_atk:f64,
1274 /// Mana Defense
1275 pub m_def:f64,
1276
1277}
1278impl Random for Stats {
1279 type Type = Stats;
1280 fn random_type(&self) -> Self::Type {
1281 let hp = self.random(10.0,50.0);
1282 let atk = self.random(5.0,50.0);
1283 let def = self.random(5.0,50.0);
1284 let mp = self.random(10.0,50.0);
1285 let m_atk = self.random(5.0,50.0);
1286 let m_def = self.random(5.0,50.0);
1287 let speed = self.random(5.0,50.0);
1288 let gp = self.random(0.0, 30.0);
1289 Stats {
1290 id:self.random(0.0, 100.0),
1291 xp:0.0,
1292 xp_next:10.0,
1293 level:1.0,
1294 hp_max:hp,
1295 hp,
1296 mp_max:mp,
1297 mp,
1298 atk,
1299 def,
1300 m_atk,
1301 m_def,
1302 speed,
1303 gp,
1304
1305 }
1306 }
1307
1308}
1309impl Stats {
1310
1311 /// make empty stats
1312 #[allow(unused)]
1313 pub fn empty() -> Self {
1314 Stats {
1315 id:0.0,
1316 xp:0.0,
1317 xp_next:0.0,
1318 mp:0.0,
1319 hp:0.0,
1320 mp_max:0.0,
1321 hp_max:0.0,
1322 level:0.0,
1323 speed:0.0,
1324 gp:0.0,
1325 atk:0.0,
1326 def:0.0,
1327 m_atk:0.0,
1328 m_def:0.0,
1329 }
1330 }
1331 /// People like new
1332 #[allow(unused)]
1333 pub fn new() -> Self {
1334 Self::empty()
1335 }
1336 #[allow(unused)]
1337 /// Get the next amount of XP needed to level up
1338 pub fn next(&self) -> f64 {
1339 self.level * self.xp_next
1340 }
1341 #[allow(unused)]
1342 /// a vector of stats used to get the standard deviation
1343 pub fn stats_vec(&self) -> Vec<f64>{
1344 vec![
1345 self.hp_max,
1346 self.mp_max,
1347 self.speed,
1348 self.atk,
1349 self.def,
1350 self.m_atk,
1351 self.m_def,
1352 ]
1353 }
1354
1355 #[allow(unused)]
1356 /// This function levels up our stats
1357 pub fn level_up(&mut self) {
1358 println!("xp:{} next:{}", self.xp, self.next());
1359 if self.xp > self.next() {
1360 let stats_vec:Vec<f64> = self.stats_vec();
1361 let mut num:f64 = Math::population_standard_deviation(stats_vec);
1362 let one = num::cast(1).unwrap();
1363 if num < one {
1364 num = one;
1365 }
1366 num *= self.level;
1367 self.level += num;
1368 self.mp_max += num;
1369 self.hp_max += num;
1370 self.speed += num;
1371 self.atk += num;
1372 self.def += num;
1373 self.m_atk += num;
1374 self.m_def += num;
1375 }
1376 }
1377}
1378
1379impl Default for Stats {
1380 /// Default to empty
1381 fn default() -> Self {
1382 Self::empty()
1383 }
1384}
1385
1386/*
1387# Premade trait for the f64/FLTK Stat
1388Define the function `stat()` to return the `Stats` associated with your code.
1389Define the methods to set the stats, and the getter functions already exist
1390
1391
1392*/
1393pub trait Premade {
1394 /// # Function you need to imlement
1395 /// stat returns the `Stats` you created
1396 fn stat(&self) -> Stats;
1397 /// # Function you need to imlement
1398 /// Set the `Stats` Health Points
1399 fn set_hp(&mut self, amount:f64);
1400 /// # Function you need to imlement
1401 /// Set the `Stats` Mana Points
1402 fn set_mp(&mut self, amount:f64);
1403 /// # Function you need to imlement
1404 /// Set the `Stats` Experience Points
1405 fn set_xp(&mut self, amount:f64);
1406 /// # Function you need to imlement
1407 /// Set the `Stats` Max Health Points
1408 fn set_hp_max(&mut self, amount:f64);
1409 /// # Function you need to imlement
1410 /// Set the `Stats` Max Mana Points
1411 fn set_mp_max(&mut self, amount:f64);
1412 /// # Function you need to imlement
1413 /// Set the `Stats` Next Experience Points
1414 fn set_xp_next(&mut self, amount:f64);
1415 /// # Function you need to imlement
1416 /// Set the `Stats` Gold Points
1417 fn set_gp(&mut self, amount:f64);
1418 /// # Function you need to imlement
1419 /// Set the `Stats` Attack Points
1420 fn set_atk(&mut self, amount:f64);
1421 /// # Function you need to imlement
1422 /// Set the `Stats` Defense Points
1423 fn set_def(&mut self, amount:f64);
1424 /// # Function you need to imlement
1425 /// Set the `Stats` Mana Attack Points
1426 fn set_m_atk(&mut self, amount:f64);
1427 /// # Function you need to imlement
1428 /// Set the `Stats` Mana Defense Points
1429 fn set_m_def(&mut self, amount:f64);
1430 /// # Function you need to imlement
1431 /// Set the `Stats` Level
1432 fn set_level(&mut self, amount:f64);
1433 /// # Function you need to imlement
1434 /// Set the `Stats` Level
1435 fn set_speed(&mut self, amount:f64);
1436
1437// PREMADE FUNCf64IONS
1438 /// Return the `Stats` id number
1439 fn id(&self) -> f64 {
1440 self.stat().id
1441 }
1442 /// Return the `Stats` Health Points
1443 fn hp(&self) -> f64 {
1444 self.stat().hp
1445 }
1446 /// Return the `Stats` Mana Points
1447 fn mp(&self) -> f64 {
1448 self.stat().mp
1449 }
1450 /// Return the `Stats` Experience Points
1451 fn xp(&self) -> f64 {
1452 self.stat().xp
1453 }
1454 /// Return the `Stats` Max Health Points
1455 fn hp_max(&self) -> f64 {
1456 self.stat().hp_max
1457 }
1458 /// Return the `Stats` Max Mana Points
1459 fn mp_max(&self) -> f64 {
1460 self.stat().mp_max
1461 }
1462 /// Return the `Stats` Next Experience Points
1463 fn xp_next(&self) -> f64 {
1464 self.stat().xp_next
1465 }
1466 /// Return the `Stats` Level
1467 fn level(&self) -> f64 {
1468 self.stat().level
1469 }
1470 /// Return the `Stats` Speed
1471 fn speed(&self) -> f64 {
1472 self.stat().speed
1473 }
1474 /// Return the `Stats` Gold Points
1475 fn gp(&self) -> f64 {
1476 self.stat().gp
1477 }
1478 /// Return the `Stats` Attack Points
1479 fn atk(&self) -> f64 {
1480 self.stat().atk
1481 }
1482 /// Return the `Stats` Defense Points
1483 fn def(&self) -> f64 {
1484 self.stat().def
1485 }
1486 /// Return the `Stats` Mana Attack Points
1487 fn m_atk(&self) -> f64 {
1488 self.stat().m_atk
1489 }
1490 /// Return the `Stats` Mana Defense Points
1491 fn m_def(&self) -> f64 {
1492 self.stat().m_def
1493 }
1494 /// Return the `Stats` Attack Points
1495 fn add_atk(&mut self, amount:f64) {
1496 self.set_atk(self.stat().atk + amount);
1497 }
1498 /// Return the `Stats` Defense Points
1499 fn add_def(&mut self, amount:f64) {
1500 self.set_def(self.stat().def + amount);
1501 }
1502 /// Return the `Stats` Mana Attack Points
1503 fn add_m_atk(&mut self, amount:f64) {
1504 self.set_m_atk(self.stat().m_atk + amount);
1505 }
1506 /// Return the `Stats` Mana Defense Points
1507 fn add_m_def(&mut self, amount:f64) {
1508 self.set_m_def(self.stat().m_def + amount);
1509 }/// Return the `Stats` Experience Points
1510 fn add_xp(&mut self, amount:f64) {
1511 self.set_xp(self.stat().xp + amount);
1512 }
1513 /// Return the `Stats` Max Health Points
1514 fn add_hp_max(&mut self, amount:f64) {
1515 self.set_hp_max(self.stat().hp_max + amount);
1516 }
1517 /// Return the `Stats` Max Mana Points
1518 fn add_mp_max(&mut self, amount:f64) {
1519 self.set_mp_max( self.stat().mp_max + amount);
1520 }
1521 /// Return the `Stats` Level
1522 fn add_level(&mut self, amount:f64) {
1523 self.set_level(self.stat().level + amount);
1524 }
1525 /// Return the `Stats` Speed
1526 fn add_speed(&mut self, amount:f64) {
1527 self.set_speed(self.stat().speed + amount);
1528 }
1529 /// Damage the character by an amount
1530 fn damage(&mut self, amount:f64) {
1531 let mut val = self.hp();
1532 val -= amount;
1533 let none = 0.0;
1534 if val < none {
1535 val = none;
1536 }
1537 self.set_hp(val)
1538 }
1539 /// Add health to character but not beyond their Max Healh Points
1540 fn heal(&mut self, amount:f64) {
1541 let mut val = self.hp();
1542 val += amount;
1543 let max = self.hp_max();
1544 if val > max {
1545 val = max;
1546 }
1547 self.set_hp(val)
1548 }
1549 /// Stable attack forumla
1550 /// [attack*(100/(100+defense))](https://rpg.fandom.com/wiki/Damage_Formula)
1551 fn attack_stable(&self, other:Stats) -> f64 {
1552 let hundred = 100.0;
1553 let val = self.atk();
1554 let def = other.def + hundred;
1555 let res = hundred / def;
1556 val * res
1557 }
1558 /// Scalable attack forumla
1559 /// [damage = att * att / (att + def)](https://gamedev.stackexchange.com/questions/129319/rpg-formula-attack-and-defense)
1560 fn attack(&self, other:Stats) -> f64 {
1561 let val = self.atk();
1562 let mut res = val * val;
1563 let def = other.def + val;
1564 res /= def;
1565 res
1566 }
1567 fn buy(&mut self, price:f64) -> bool {
1568 let total = self.gp() - price;
1569 if total <= 0.0 {
1570 return false;
1571 }
1572 self.set_gp(total);
1573 true
1574 }
1575 fn earn(&mut self, price:f64) {
1576 let total = self.gp() + price;
1577 self.set_gp(total);
1578 } #[allow(unused)]
1579 /// Get the next amount of XP needed to level up
1580 fn next(&self) -> f64 {
1581 self.level() * self.xp_next()
1582 }
1583 /// a vector of stats used to get the standard deviation
1584 fn stats_vec(&self) -> Vec<f64>{
1585 vec![
1586 self.hp_max(),
1587 self.mp_max(),
1588 self.speed(),
1589 self.atk(),
1590 self.def(),
1591 self.m_atk(),
1592 self.m_def(),
1593 ]
1594 }
1595
1596 #[allow(unused)]
1597 fn level_up(&mut self) -> bool{
1598 if self.xp() > self.next() {
1599 let stats_vec:Vec<f64> = self.stats_vec();
1600 let mut num:f64 = Math::population_standard_deviation(stats_vec);
1601 let one = 1.0;
1602 if num < one {
1603 num = one;
1604 }
1605 self.add_level(num);
1606 self.add_mp_max(num);
1607 self.add_hp_max(num);
1608 self.add_speed(num);
1609 self.add_atk(num);
1610 self.add_def(num);
1611 self.add_m_atk(num);
1612 self.add_m_def(num);
1613 return true;
1614 }
1615 false
1616 }
1617}