rpg_stat/
creature.rs

1/*!
2# Creature Stats
3
4Easy to `generate()` an editable version, or use `view()` to simple view the stats as an FLTK group
5```
6#[cfg(feature = "fltkform")]
7fn run () {
8    use fltk::{prelude::*, *};
9    use fltk_form_derive::*;
10    use fltk_form::FltkForm;
11    use rpg_stat::random::Random;
12    use rpg_stat::creature::Stats;
13    let c = Stats::default();
14    let app = app::App::default();
15    let mut win = window::Window::default().with_size(400, 300);
16    let my_struct = c.random_type();
17    let mut grp = group::Scroll::default()
18                    .with_size(300, 200)
19                    .center_of_parent();
20    let form = my_struct.generate();
21    grp.end();
22    win.end();
23    while app.wait() {
24        win.redraw();
25    }
26}
27```
28*/
29use serde::{Deserialize, Serialize};
30use std::fmt::Debug;
31
32// #Normal
33// #Special
34use crate::special::Normal as Special;
35use crate::special::SpecialMove;
36use crate::item::Item;
37use crate::item::Normal as MyItem;
38// #Condition
39use crate::effect::Normal as Condition;
40// #Element
41use crate::types::Normal as Element;
42use crate::types::Advanced as Element2;
43use crate::attributes::{Stage, Rate};//, Effectiveness};
44use crate::random::*;
45
46#[cfg(feature = "fltkform")]
47use fltk::{prelude::*, *};
48#[cfg(feature = "fltkform")]
49use fltk_form_derive::*;
50#[cfg(feature = "fltkform")]
51use fltk_form::FltkForm;
52
53/*
54# Stats Stats
55
56These stats exist for the sole purpose of raising and training creatures
57This stat is based off of the ideas of the original Pokemon save memory data structure, but for use with the rpg_stat library.
58*/
59#[derive( Debug, Clone, PartialEq, Serialize, Deserialize)]
60#[cfg_attr(feature = "fltkform", derive(FltkForm))]
61pub struct Stats {
62    /// Identification number
63    pub id:u32,
64    /// Name of creature
65    pub name:String,
66    /// Current Stage
67    pub form:Stage,
68    /// Current status/ailment condition
69    pub condition:Condition,
70    /// Normal element type
71    pub element1:Element,
72    /// Advanced element type
73    pub element2:Element2,
74    /// The rate of occurrence, or rate of success
75    pub rate:Rate,
76    /// this is the owner's id
77    pub owner:u32,
78    /// level cycle xp (for display)
79    pub xp:f64,
80    /// Total XP
81    pub total_xp:f64,
82    /// Experience points for leveling Health Points
83    pub hp_xp:f64,
84    /// Experience points for leveling Attack
85    pub atk_xp:f64,
86    /// Experience points for leveling Defense
87    pub def_xp:f64,
88    /// Experience points for leveling Speed
89    pub speed_xp:f64,
90    /// Experience points for leveling Special
91    pub special_xp:f64,
92    /// Current level
93    pub level:f64,
94    /// Maximum Health Points
95    pub hp_max:f64,
96    /// Current Health Points
97    pub hp:f64,
98    /// Attack power
99    pub atk:f64,
100    /// Defense capability
101    pub def:f64,
102    /// Speed of creature in battle, or as they move
103    pub speed:f64,
104    /// 
105    pub special:f64,
106    /// Putting a file name here generates a picture
107    pub image:String,
108    /// [Special Move](@TODO@)
109    pub move0:Special,
110    /// Mana Points for Special move 0
111    pub move0_mp:f64,
112    /// [Special Move](@TODO@)
113    pub move1:Special,
114    /// Mana Points for Special move 1
115    pub move1_mp:f64,
116    /// [Special Move](@TODO@)
117    pub move2:Special,
118    /// Mana Points for Special move 2
119    pub move2_mp:f64,
120    /// [Special Move](@TODO@)
121    pub move3:Special,
122    /// Mana Points for Special move 3
123    pub move3_mp:f64,
124    /// [Special Move](@TODO@)
125    pub move4:Special,
126    /// Mana Points for Special move 4
127    pub move4_mp:f64,
128    /// [MyItem type](@todo@)
129    pub item0:MyItem,
130    /// Number of items in slot 0
131    pub items0:f64,
132    /// [MyItem type](@todo@)
133    pub item1:MyItem,
134    /// Number of items in slot 1
135    pub items1:f64,
136    /// [MyItem type](@todo@)
137    pub item2:MyItem,
138    /// Number of items in slot 2
139    pub items2:f64,
140    /// [MyItem type](@todo@)
141    pub item3:MyItem,
142    /// Number of items in slot 3
143    pub items3:f64,
144    /// [MyItem type](@todo@)
145    pub item4:MyItem,
146    /// Number of items in slot 4
147    pub items4:f64,
148}
149impl  Default for Stats {
150    fn default() -> Self where Self:Sized {
151        Self::new()
152    }
153}
154impl Random for Stats {
155    type Type = Stats;
156    fn random_type(&self) -> Self::Type {
157        let mut element1 = Element::Rock;
158        element1 = element1.random_type();
159        let hp = self.random(10.0,50.0);
160        let atk = self.random(5.0,50.0);
161        let def = self.random(5.0,50.0);
162        let speed = self.random(5.0,50.0);
163        let special = self.random(5.0,50.0);
164        let form = Stage::Teen;
165        let spec = Special::None;
166        let item = MyItem::None;
167        let move0 = spec.random_type();
168        let move1 = spec.random_type();
169        let rate = Rate::None;
170        Stats {
171            id:self.random_rate(100),
172            name:random_creature_name(),
173            form:form.random_type(),
174            condition:Condition::None,
175            element1,
176            element2:Element2::None,
177            rate:rate.random_type(),
178            move0,
179            move0_mp:move0.mp_total(0.0),
180            move1,
181            move1_mp:move1.mp_total(0.0),
182            move2:spec,
183            move2_mp:0.0,
184            move3:spec,
185            move3_mp:0.0,
186            move4:spec,
187            move4_mp:0.0,
188            item0:item,
189            items0:0.0,
190            item1:item,
191            items1:0.0,
192            item2:item,
193            items2:0.0,
194            item3:item,
195            items3:0.0,
196            item4:item,
197            items4:0.0,
198            owner:0,
199            xp:0.0,
200            total_xp:0.0,
201            hp_xp:hp,
202            atk_xp:atk,
203            def_xp:def,
204            speed_xp:speed,
205            special_xp:special,
206            level:1.0,
207            hp_max:hp,
208            hp,
209            atk,
210            def,
211            speed,
212            special,
213            image:String::from(""),
214            
215        }
216    }
217    
218}
219impl Stats {
220/*
221```
222use rpg_stat::random::Random;
223use rpg_stat::creature::Stats;
224use rpg_stat::item::Item;
225use rpg_stat::item::Normal as MyItem;
226
227let mut stat = Stats::default();
228stat = stat.random_type();
229let captured = stat.check_capture();
230if captured {
231  println!("Captured: {:?}", stat.name.to_owned());
232}
233if stat.check_encounter() {
234  println!("Found: {:?}", stat.name.to_owned());
235
236}
237if stat.heal(100.0) {
238  println!("Healed: {:?}", stat.name.to_owned());
239
240}
241if stat.use_item(1) {
242  println!("Used Item on {:?}", stat.name.to_owned());
243
244}
245if stat.get_item(1) {
246  println!("Got item #1 from: {:?}", stat.name.to_owned());
247
248}
249if !stat.remove_item(3) {
250  println!("{:?} has no item #3 to remove", stat.name.to_owned());
251
252}
253for item in stat.items {
254    println!("Item: {:?}", item);
255}
256if stat.add_item(MyItem::Special) {
257    println!("Added Item 'Special'");
258}
259let clone = stats.clone();
260```
261*/
262    #[allow(unused)]
263    pub fn check_capture(&self) -> bool {
264        self.rate.worked()
265    }
266    #[allow(unused)]
267    pub fn check_encounter(&self) -> bool {
268        self.rate.worked()
269    }
270    #[allow(unused)]
271    pub fn heal(&mut self, value:f64) -> bool {
272        if value < 0.0 {
273            return false;
274        }
275        self.hp += value;
276        if self.hp > self.hp_max {
277            self.hp = self.hp_max;
278        }
279        true
280    }
281    #[allow(unused)]
282    pub fn next(&self) -> f64 {
283        self.level * 20.0
284    }
285    #[allow(unused)]
286    pub fn level_up(&mut self) {
287        println!("xp:{} next:{} total:{}", self.xp, self.next(), self.total_xp);
288        self.total_xp += self.xp;
289        if self.xp > self.next() {
290            if self.hp_xp > self.hp_max {
291               self.hp_max = self.hp_xp; 
292            } else {
293                self.hp_xp += self.level;
294            }
295            if self.atk_xp > self.atk {
296                self.atk = self.atk_xp; 
297            } else {
298                self.atk_xp += self.level;
299            }
300            if self.def_xp > self.def {
301                self.def = self.def_xp; 
302            } else {
303                self.def_xp += self.level;
304            }
305            if self.speed_xp > self.speed {
306                self.speed = self.speed_xp; 
307            } else {
308                self.speed_xp += self.level;
309            }
310            if self.special_xp > self.special {
311                self.special = self.special_xp; 
312            } else {
313                self.special_xp += self.level;
314            }
315            self.level += 1.0;
316            self.xp = 0.0;
317        }
318        println!("level:{}",self.level);
319    }
320    #[allow(unused)]
321    pub fn new() -> Self {
322        Stats {
323            id:0,
324            name:String::from(""),
325            form:Stage::Baby,
326            condition:Condition::None,
327            element1:Element::None,
328            element2:Element2::None,
329            rate:Rate::None,
330            item0:MyItem::None,
331            items0:0.0,
332            item1:MyItem::None,
333            items1:0.0,
334            item2:MyItem::None,
335            items2:0.0,
336            item3:MyItem::None,
337            items3:0.0,
338            item4:MyItem::None,
339            items4:0.0,
340            move0:Special::None,
341            move0_mp:0.0,
342            move1:Special::None,
343            move1_mp:0.0,
344            move2:Special::None,
345            move2_mp:0.0,
346            move3:Special::None,
347            move3_mp:0.0,
348            move4:Special::None,
349            move4_mp:0.0,
350            owner:0,
351            xp:0.0,
352            total_xp:0.0,
353            hp_xp:0.0,
354            atk_xp:0.0,
355            def_xp:0.0,
356            speed_xp:0.0,
357            special_xp:0.0,
358            level:0.0,
359            hp_max:0.0,
360            hp:0.0,
361            atk:0.0,
362            def:0.0,
363            speed:0.0,
364            special:0.0,
365            image:String::from(""),
366        }
367    }
368    #[allow(unused)]
369    pub fn use_mp(&mut self, move_number:u32) -> bool {
370        let value = 1.0;
371        match move_number {
372            0 => self.move0_mp -= value,
373            1 => self.move1_mp -= value,
374            2 => self.move2_mp -= value,
375            3 => self.move3_mp -= value,
376            4 => self.move4_mp -= value,
377            _=> return false,
378        }
379        true
380    }
381    #[allow(unused)]
382    pub fn get_mp(&self, move_number:u32) -> f64 {
383        match move_number {
384            0 => self.move0_mp,
385            1 => self.move1_mp,
386            2 => self.move2_mp,
387            3 => self.move3_mp,
388            4 => self.move4_mp,
389            _=> 0.0,
390        }
391    }
392    #[allow(unused)]
393    pub fn restore_mp(&mut self, move_number:u32, value:f64) -> bool {
394        match move_number {
395            0 => {
396                self.move0_mp += value;
397                let limit = self.move0.mp_total(0.0);
398                if self.move0_mp > limit {
399                    self.move0_mp = limit;
400                }
401            },
402            1 => {
403                self.move1_mp += value;
404                let limit = self.move1.mp_total(0.0);
405                if self.move1_mp > limit {
406                    self.move1_mp = limit;
407                }
408            },
409            2 => {
410                self.move2_mp += value;
411                let limit = self.move2.mp_total(0.0);
412                if self.move2_mp > limit {
413                    self.move2_mp = limit;
414                }
415            },
416            3 => {
417                self.move3_mp += value;
418                let limit = self.move3.mp_total(0.0);
419                if self.move3_mp > limit {
420                    self.move3_mp = limit;
421                }
422            },
423            4 => {
424                self.move4_mp += value;
425                let limit = self.move4.mp_total(0.0);
426                if self.move4_mp > limit {
427                    self.move4_mp = limit;
428                }
429            },
430            _=> return false,
431        }
432        true
433    }
434    #[allow(unused)]
435    pub fn moves(&self) -> Vec<Special> {
436        let mut vec:Vec<Special> = vec![];
437        if self.move0 != Special::None {
438            vec.push(self.move0);
439        }
440        if self.move1 != Special::None {
441            vec.push(self.move1);
442        }
443        if self.move2 != Special::None {
444            vec.push(self.move2);
445        }
446        if self.move3 != Special::None {
447            vec.push(self.move3);
448        }
449        if self.move4 != Special::None {
450            vec.push(self.move4);
451        }
452        vec
453    }
454    #[allow(unused)]
455    pub fn add_move(&mut self, special:Special) -> bool {
456        if self.move0 != Special::None {
457            self.move0 = special;
458            return true;
459        }
460        if self.move1 != Special::None {
461            self.move1 = special;
462            return true;
463        }
464        if self.move2 != Special::None {
465            self.move2 = special;
466            return true;
467        }
468        if self.move3 != Special::None {
469            self.move3 = special;
470            return true;
471        }
472        if self.move4 != Special::None {
473            self.move4 = special;
474            return true;
475        }
476        false
477    }
478    #[allow(unused)]
479    pub fn remove_move(&mut self, move_number:u32) -> bool {
480        match move_number {
481            0 => self.move0 = Special::None,
482            1 => self.move1 = Special::None,
483            2 => self.move2 = Special::None,
484            3 => self.move3 = Special::None,
485            4 => self.move4 = Special::None,
486            _=> return false,
487        }
488        true
489    }
490    #[allow(unused)]
491    pub fn get_move(&self, move_number:u32) -> Special {
492        match move_number {
493            4 => self.move4,
494            1 => self.move1,
495            2 => self.move2,
496            3 => self.move3,
497            _=> self.move0,
498        }
499    }
500    #[allow(unused)]
501    pub fn valid_move(&self, move_number:u32) -> bool {
502        match move_number {
503            1 => !(self.move1 == Special::None),
504            2 => !(self.move2 == Special::None),
505            3 => !(self.move3 == Special::None),
506            4 => !(self.move4 == Special::None),
507            _=> !(self.move0 == Special::None),
508        }
509    }
510    #[allow(unused)]
511    pub fn damage_attack(&mut self, atk_move:Special) -> f64 {
512        //first math
513        let dmg = atk_move.damage(self.level);
514        dmg * self.atk
515    }
516    #[allow(unused)]
517    pub fn special(&mut self, id:usize, other:Stats) -> Option<f64> {
518        let vec = self.moves();
519        if vec.len() < id {
520            return None
521        }
522        let atk_move = vec[id];
523        let mut result = self.damage_attack(atk_move);//dmg * self.atk
524        let def = other.def + other.hp;
525        if result == 0.0 {
526            result = def;
527        }
528        result /= def;
529        if result > other.hp {
530            result = other.hp;
531        }
532        Some(result)
533    }
534    #[allow(unused)]
535    pub fn items(&self) -> Vec<MyItem> {
536        let mut vec:Vec<MyItem> = vec![];
537        if self.item0 != MyItem::None {
538            vec.push(self.item0);
539        }
540        if self.item1 != MyItem::None {
541            vec.push(self.item1);
542        }
543        if self.item2 != MyItem::None {
544            vec.push(self.item2);
545        }
546        if self.item3 != MyItem::None {
547            vec.push(self.item3);
548        }
549        if self.item4 != MyItem::None {
550            vec.push(self.item4);
551        }
552        vec
553    }
554    #[allow(unused)]
555    pub fn add_item(&mut self, special:MyItem) -> bool {
556        if self.item0 != MyItem::None {
557            self.item0 = special;
558            return true;
559        }
560        if self.item1 != MyItem::None {
561            self.item1 = special;
562            return true;
563        }
564        if self.item2 != MyItem::None {
565            self.item2 = special;
566            return true;
567        }
568        if self.item3 != MyItem::None {
569            self.item3 = special;
570            return true;
571        }
572        if self.item4 != MyItem::None {
573            self.item4 = special;
574            return true;
575        }
576        false
577    }
578    #[allow(unused)]
579    pub fn remove_item(&mut self, item_number:u32) -> bool {
580        match item_number {
581            0 => self.item0 = MyItem::None,
582            1 => self.item1 = MyItem::None,
583            2 => self.item2 = MyItem::None,
584            3 => self.item3 = MyItem::None,
585            4 => self.item4 = MyItem::None,
586            _=> return false,
587        }
588        true
589    }
590    #[allow(unused)]
591    pub fn get_item(&self, item_number:u32) -> MyItem {
592        match item_number {
593            0 => self.item0,
594            1 => self.item1,
595            2 => self.item2,
596            3 => self.item3,
597            _=> self.item4,
598        }
599    }
600
601    #[allow(unused)]
602    pub fn use_item(&mut self, item_number:u32) -> bool {
603        let item:MyItem;
604        match item_number {
605            0 => item = self.item0,
606            1 => item = self.item1,
607            2 => item = self.item2,
608            3 => item = self.item3,
609            4=> item = self.item4,
610            _=> return false,
611        }
612        let val = item.value();
613        match item {
614            MyItem::Hp => return self.heal(val),
615            MyItem::Mp => return self.restore_mp(item_number, val),
616            MyItem::Heal => self.condition = Condition::None,
617            MyItem::Exp => self.xp += val,
618            MyItem::Def => self.def += val,
619            MyItem::Atk => self.atk += val,
620            MyItem::Speed => self.speed += val,
621            MyItem::Special => self.special += val,
622            _=> return false,
623        }
624        true
625    }
626}