1 /*
2 * This file is part of EasyRPG Player.
3 *
4 * EasyRPG Player is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
8 *
9 * EasyRPG Player is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with EasyRPG Player. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18 #ifndef EP_GAME_CHARACTER_H
19 #define EP_GAME_CHARACTER_H
20
21 // Headers
22 #include <string>
23 #include "color.h"
24 #include "flash.h"
25 #include <lcf/rpg/moveroute.h>
26 #include <lcf/rpg/eventpage.h>
27 #include <lcf/rpg/savemapeventbase.h>
28 #include "utils.h"
29
30 /**
31 * Game_Character class.
32 */
33 class Game_Character {
34 public:
35 using AnimType = lcf::rpg::EventPage::AnimType;
36
37 enum Type {
38 Event,
39 Player,
40 Vehicle
41 };
42
43 static StringView TypeToStr(Type t);
44
45 /**
46 * Destructor.
47 */
48 virtual ~Game_Character();
49
50 /** @return the type of character this is */
51 Type GetType() const;
52
53 /**
54 * Gets x position in tiles.
55 *
56 * @return x position.
57 */
58 int GetX() const;
59
60 /**
61 * Sets x position in tiles.
62 *
63 * @param new_x new x position.
64 */
65 void SetX(int new_x);
66
67 /**
68 * Gets y position in tiles.
69 *
70 * @return y position.
71 */
72 int GetY() const;
73
74 /**
75 * Sets y position in tiles.
76 *
77 * @param new_y new y position.
78 */
79 void SetY(int new_y);
80
81 /**
82 * Gets the map id the character was inititialy on.
83 *
84 * @return map id.
85 */
86 int GetMapId() const;
87
88 /**
89 * Sets the map id the character was inititialy on.
90 *
91 * @param new_map_id New map id of character.
92 */
93 void SetMapId(int new_map_id);
94
95 /**
96 * Gets character's movement direction.
97 *
98 * @return current front direction.
99 */
100 int GetDirection() const;
101
102 /**
103 * Sets character's movement direction.
104 *
105 * @param new_direction New current front direction.
106 */
107 void SetDirection(int new_direction);
108
109 /**
110 * Gets character's visible facing direction.
111 *
112 * @return direction of the sprite.
113 */
114 int GetFacing() const;
115
116 /**
117 * Sets character's visible facing direction.
118 *
119 * @param new_direction New facing direction.
120 */
121 void SetFacing(int new_direction);
122
123 /**
124 * Gets whether facing is locked.
125 *
126 * @return facing locked
127 */
128 bool IsFacingLocked() const;
129
130 /**
131 * Enables or disables locked facing direction.
132 *
133 * @param locked true: locked, false: unlocked.
134 */
135 void SetFacingLocked(bool locked);
136
137 /**
138 * Gets the event layer (top, same, below).
139 *
140 * @return event layer
141 */
142 int GetLayer() const;
143
144 /**
145 * Sets the event layer (top, same, below).
146 *
147 * @param new_layer New event layer
148 */
149 void SetLayer(int new_layer);
150
151 /**
152 * Gets whether other events can be in the same tile.
153 *
154 * @return whether event overlap is forbidden.
155 */
156 bool IsOverlapForbidden() const;
157
158 /**
159 * Gets character movement speed.
160 *
161 * @return character movement speed
162 */
163 int GetMoveSpeed() const;
164
165 /**
166 * Sets character movement speed.
167 *
168 * @param speed new movement speed
169 */
170 void SetMoveSpeed(int speed);
171
172 /**
173 * Gets character movement frequency.
174 *
175 * @return character movement frequency
176 */
177 int GetMoveFrequency() const;
178
179 /**
180 * Sets character movement frequency.
181 *
182 * @param frequency new character movement frequency
183 */
184 void SetMoveFrequency(int frequency);
185
186 /**
187 * Returns the custom move route assigned via a MoveEvent.
188 *
189 * @return custom move route
190 */
191 const lcf::rpg::MoveRoute& GetMoveRoute() const;
192
193 /**
194 * Sets a new custom move route. Used to assign a new MoveEvent.
195 *
196 * @param move_route new custom move route
197 */
198 void SetMoveRoute(const lcf::rpg::MoveRoute& move_route);
199
200 /**
201 * Returns current index of the route assigned via a MoveEvent.
202 *
203 * @return current move route index
204 */
205 int GetMoveRouteIndex() const;
206
207 /**
208 * Sets current index of a MoveEvent move route.
209 *
210 * @param new_index New custom move route index
211 */
212 void SetMoveRouteIndex(int new_index);
213
214 /**
215 * Gets whether move route is overwritten by event.
216 *
217 * @return move route overwritten
218 */
219 bool IsMoveRouteOverwritten() const;
220
221 /**
222 * Enables/Disables overwriting of move routes.
223 *
224 * @param force true: Use default move scheme, false: Use custom move route
225 */
226 void SetMoveRouteOverwritten(bool force);
227
228 /**
229 * Checks if the forced move route has been repeating itself.
230 *
231 * @return whether forced move route has been repeating itself
232 */
233 bool IsMoveRouteRepeated() const;
234
235 /**
236 * Makes current forced move route repeated/non-repeated.
237 *
238 * @param repeat true: Repeated move route, false: Non-repeated move route
239 */
240 void SetMoveRouteRepeated(bool repeat);
241
242 /**
243 * Gets sprite name. Usually the name of the graphic file.
244 *
245 * @return sprite name
246 */
247 const std::string& GetSpriteName() const;
248
249 /** @return true if this has a tile sprite */
250 bool HasTileSprite() const;
251
252 /**
253 * Sets sprite name. Usually the name of the graphic file.
254 *
255 * @param sprite_name new sprite name
256 * @param index the index of the new sprite.
257 */
258 void SetSpriteGraphic(std::string sprite_name, int index);
259
260 /**
261 * Sets sprite name from a move route command. Usually the name of the graphic file.
262 * This can be overridden to change behavior by child classes.
263 *
264 * @param sprite_name new sprite name
265 * @param index the index of the new sprite.
266 */
267 virtual void MoveRouteSetSpriteGraphic(std::string sprite_name, int index);
268
269 /**
270 * Gets sprite index of character.
271 *
272 * @return sprite index
273 */
274 int GetSpriteIndex() const;
275
276 /**
277 * Gets animation frame of character.
278 *
279 * @return anim_frame
280 */
281 int GetAnimFrame() const;
282
283 /**
284 * Sets animation frame of character.
285 *
286 * @param frame new anim_frame
287 */
288 void SetAnimFrame(int frame);
289
290 /**
291 * @return true if animation is paused.
292 */
293 bool IsAnimPaused() const;
294
295 /**
296 * Sets whether animation is paused.
297 *
298 * @param value whether to pause the animation.
299 */
300 void SetAnimPaused(bool value);
301
302 /**
303 * Updates the sprite facing direction based on current direction
304 */
305 void UpdateFacing();
306
307 /**
308 * Begins a flash.
309 *
310 * @param r red color
311 * @param g blue color
312 * @param b green color
313 * @param power power of the flash
314 * @param frames Duration of the flash in frames
315 */
316 void Flash(int r, int g, int b, int power, int frames);
317
318 /**
319 * Gets flash effect color.
320 *
321 * @return flash color
322 */
323 Color GetFlashColor() const;
324
325 /**
326 * Returns intensity of flash effect.
327 *
328 * @return flash intensity
329 */
330 double GetFlashLevel() const;
331
332 /**
333 * Sets intensity of flash effect.
334 *
335 * @param flash_level new flash intensity
336 */
337 void SetFlashLevel(double flash_level);
338
339 /**
340 * Returns how many flash effect time is left.
341 *
342 * @return time left
343 */
344 int GetFlashTimeLeft() const;
345
346 /**
347 * Set how long the flash effect will take.
348 *
349 * @param time_left flash duration
350 */
351 void SetFlashTimeLeft(int time_left);
352
353 /**
354 * Gets the through flag (walk through everything)
355 *
356 * @return through flag
357 */
358 bool GetThrough() const;
359
360 /**
361 * Sets the through flag (walk through everything)
362 *
363 * @param through through flag
364 */
365 void SetThrough(bool through);
366
367 /** Resets the through flag to the route_through flag */
368 void ResetThrough();
369
370 /**
371 * @return stop_count
372 */
373 int GetStopCount() const;
374
375 /**
376 * Sets the stop_count
377 *
378 * @param sc the new stop count
379 */
380 void SetStopCount(int sc);
381
382 /**
383 * @return max_stop_count
384 */
385 int GetMaxStopCount() const;
386
387 /**
388 * @return stepping max_stop_count for the given frequency
389 * @param freq input movement frequency
390 */
391 static constexpr int GetMaxStopCountForStep(int freq);
392
393 /**
394 * @return turning max_stop_count for the given frequency
395 * @param freq input movement frequency
396 */
397 static constexpr int GetMaxStopCountForTurn(int freq);
398
399 /**
400 * @return waiting max_stop_count for the given frequency
401 * @param freq input movement frequency
402 */
403 static constexpr int GetMaxStopCountForWait(int freq);
404
405 /**
406 * @return the number of frames for animating steps while not moving
407 * @param speed the movement speed.
408 */
409 static constexpr int GetStationaryAnimFrames(int speed);
410
411 /**
412 * @return the number of frames for animating steps while moving or continuous.
413 * @param speed the movement speed.
414 */
415 static constexpr int GetContinuousAnimFrames(int speed);
416
417 /**
418 * @return the number of frames for animating steps while spinning.
419 * @param speed the movement speed.
420 */
421 static constexpr int GetSpinAnimFrames(int speed);
422
423 /**
424 * Sets the max_stop_count
425 *
426 * @param sc the new max stop count
427 */
428 void SetMaxStopCount(int sc);
429
430 /** @return true if waiting for stop count in movement to complete */
431 bool IsStopCountActive() const;
432
433 /**
434 * @return anim_count
435 */
436 int GetAnimCount() const;
437
438 /**
439 * Sets the stop_count
440 *
441 * @param ac the new anim count.
442 */
443 void SetAnimCount(int ac);
444
445 /** Resets the stepping animation */
446 void ResetAnimation();
447
448 /**
449 * Gets if character is moving.
450 *
451 * @return whether the character is moving.
452 */
453 bool IsMoving() const;
454
455 /**
456 * @return whether the character is jumping.
457 */
458 bool IsJumping() const;
459
460 /**
461 * Set whether the character is jumping.
462 *
463 * @param val flag indicating jumping status
464 */
465 void SetJumping(bool val);
466
467 /**
468 * @return X position where jump began.
469 */
470 int GetBeginJumpX() const;
471
472 /**
473 * Set X position where jump began.
474 *
475 * @param x x position where jump began
476 */
477 void SetBeginJumpX(int x);
478
479 /**
480 * @return Y position where jump began.
481 *
482 * @param y y position where jump began
483 */
484 int GetBeginJumpY() const;
485
486 /**
487 * Set Y position where jump began.
488 */
489 void SetBeginJumpY(int y);
490
491 /**
492 * @return whether the character is flying.
493 */
494 bool IsFlying() const;
495
496 /**
497 * Set whether the character is flying.
498 *
499 * @param val whether or not character is flying.
500 */
501 void SetFlying(bool val);
502
503 /**
504 * @return whether the RPG_RT processed flag is set.
505 */
506 bool IsProcessed() const;
507
508 /**
509 * Set the RPG_RT processed flag
510 */
511 void SetProcessed(bool val);
512
513 /**
514 * @return whether the event is paused.
515 */
516 bool IsPaused() const;
517
518 /**
519 * Set the paused flag
520 */
521 void SetPaused(bool val);
522
523 /**
524 * Activates or deactivates the event.
525 *
526 * @param active enables or disables the event.
527 */
528 void SetActive(bool active);
529
530 /**
531 * Gets if the event is active.
532 *
533 * @return if the event is active (or inactive via EraseEvent-EventCommand).
534 */
535 bool IsActive() const;
536
537 /**
538 * Checks if the character is stopping.
539 *
540 * @return whether the character is stopping.
541 */
542 bool IsStopping() const;
543
544 /**
545 * Moves the character to a new location.
546 *
547 * @param map_id map id
548 * @param x tile x.
549 * @param y tile y.
550 */
551 virtual void MoveTo(int map_id, int x, int y);
552
553 /**
554 * Move in the direction dir.
555 *
556 * @param dir the direction to move to.
557 *
558 * @return Whether move was successful or a move or jump is already in progress.
559 * @post If successful, IsStopping() == false.
560 */
561 virtual bool Move(int dir);
562
563 /**
564 * Jump to (x, y)
565 *
566 * @param x the x position to jump to.
567 * @param y the y position to jump to.
568 *
569 * @return Whether jump was successful or a move or jump is already in progress.
570 * @post If successful, IsStopping() == false.
571 */
572 bool Jump(int x, int y);
573
574 /**
575 * Check if this can move to the given tile.
576 *
577 * @param from_x Moving from x position
578 * @param from_y Moving from y position
579 * @param to_x Moving from x position
580 * @param to_y Moving from y position
581 *
582 * @return true if this can occupy (to_x, to_y) from (from_x, from_y)
583 */
584 virtual bool MakeWay(int from_x, int from_y, int to_x, int to_y);
585
586 /**
587 * Turns the character 90 Degree to the left.
588 */
589 void Turn90DegreeLeft();
590
591 /**
592 * Turns the character 90 Degree to the right.
593 */
594 void Turn90DegreeRight();
595
596 /**
597 * Turns the character by 180 degree
598 */
599 void Turn180Degree();
600
601 /**
602 * Turns the character 90 Degree to the left or right
603 * by using a random number.
604 */
605 void Turn90DegreeLeftOrRight();
606
607 /** @return the direction we would need to face the hero. */
608 int GetDirectionToHero();
609
610 /** @return the direction we would need to face away from hero. */
611 int GetDirectionAwayHero();
612
613 /**
614 * @param dir input direction
615 *
616 * @return the direction 90 degrees to the left of dir
617 */
618 static constexpr int GetDirection90DegreeLeft(int dir);
619
620 /**
621 * @param dir input direction
622 *
623 * @return the direction 90 degrees to the right of dir
624 */
625 static constexpr int GetDirection90DegreeRight(int dir);
626
627 /**
628 * @param dir input direction
629 *
630 * @return the direction 180 degrees to the of dir
631 */
632 static constexpr int GetDirection180Degree(int dir);
633
634 /**
635 * Character looks in a random direction
636 */
637 void TurnRandom();
638
639 /**
640 * Character looks towards the hero.
641 */
642 void TurnTowardHero();
643
644 /**
645 * Character looks away from the hero.
646 */
647 void TurnAwayFromHero();
648
649 /**
650 * Character waits for 20 frames more.
651 */
652 void Wait();
653
654 /**
655 * Forces a new, temporary, move route.
656 *
657 * @param new_route new move route.
658 * @param frequency frequency.
659 */
660 void ForceMoveRoute(const lcf::rpg::MoveRoute& new_route, int frequency);
661
662 /**
663 * Cancels a previous forced move route.
664 */
665 void CancelMoveRoute();
666
667 /** @return height of active jump in pixels */
668 int GetJumpHeight() const;
669
670 /**
671 * Gets sprite x coordinate transformed to screen coordinate in pixels.
672 *
673 * @param apply_shift When true the coordinate is shifted by the map width (for looping maps)
674 * @return screen x coordinate in pixels.
675 */
676 virtual int GetScreenX(bool apply_shift = false) const;
677
678 /**
679 * Gets sprite y coordinate transformed to screen coordinate in pixels.
680 *
681 * @param apply_shift When true the coordinate is shifted by the map height (for looping maps)
682 * @param apply_jump Apply jump height modifier if character is jumping
683 * @return screen y coordinate in pixels.
684 */
685 virtual int GetScreenY(bool apply_shift = false, bool apply_jump = true) const;
686
687 /**
688 * Gets screen z coordinate in pixels.
689 *
690 * @param apply_shift Forwarded to GetScreenY
691 * @return screen z coordinate in pixels.
692 */
693 virtual int GetScreenZ(bool apply_shift = false) const;
694
695 /**
696 * Gets tile graphic ID.
697 *
698 * @return tile graphic ID.
699 */
700 int GetTileId() const;
701
702 /**
703 * Gets sprite x position in pixels.
704 *
705 * @return real x.
706 */
707 int GetSpriteX() const;
708
709 /**
710 * Gets sprite y position in pixels.
711 *
712 * @return real y.
713 */
714 int GetSpriteY() const;
715
716 /**
717 * Gets remaining step
718 *
719 * @return remaining step
720 */
721 int GetRemainingStep() const;
722
723 /**
724 * Sets remaining step
725 *
726 * @param step new remaining step count
727 */
728 void SetRemainingStep(int step);
729
730 /**
731 * Gets animation type.
732 *
733 * @return animation type.
734 */
735 AnimType GetAnimationType() const;
736
737 /**
738 * Sets animation type.
739 *
740 * @param anim_type new animation type.
741 */
742 void SetAnimationType(AnimType anim_type);
743
744 int DistanceXfromPlayer() const;
745 int DistanceYfromPlayer() const;
746
747 /**
748 * Tests if the character is currently on the tile at x/y or moving
749 * towards it.
750 *
751 * @param x X tile position
752 * @param y Y tile position
753 * @return If on tile or moving towards
754 */
755 virtual bool IsInPosition(int x, int y) const;
756
757 /**
758 * Gets current opacity of character.
759 *
760 * @return opacity (0 = Invisible, 255 = opaque)
761 */
762 int GetOpacity() const;
763
764 /**
765 * @return RPG_RT transparency
766 */
767 int GetTransparency() const;
768
769 /**
770 * Sets transparency of the character.
771 *
772 * @param value New transparency (0 = Opaque, 7 = mostly transparent)
773 */
774 void SetTransparency(int value);
775
776 /**
777 * Gets if the character is visible.
778 *
779 * @return if visible, when true Opaque value is used
780 */
781 virtual bool IsVisible() const;
782
783 /**
784 * Makes character visible/not visible.
785 * This has a higher priority then the Opacity setting.
786 * Needed for the "SetHeroTransparency" command because this can't be
787 * altered via the "Increase Transparency" move command.
788 *
789 * @param hidden true: invisible, false: visible
790 */
791 void SetSpriteHidden(bool hidden);
792
793 /** @return true if sprite is hidden */
794 bool IsSpriteHidden() const;
795
796 /**
797 * Tests if animation type is any fixed state.
798 *
799 * @return Whether direction is fixed
800 */
801 static constexpr bool IsDirectionFixedAnimationType(AnimType);
802
803 /**
804 * Tests if the step animation is enabled.
805 * The animation is enabled when the animation type is not "fixed_graphic" and when
806 * the animation was not disabled through the move command "stop animation".
807 *
808 * @return Wheter animations are enabled.
809 */
810 bool IsAnimated() const;
811
812 /**
813 * Tests if animation type is any continuous state.
814 *
815 * @return Whether animation is continuous
816 */
817 bool IsContinuous() const;
818
819 /**
820 * Tests if animation is of the type spin.
821 *
822 * @return Whether animation is spin type
823 */
824 bool IsSpinning() const;
825
826 /**
827 * Gets the bush depth of the tile where this character is standing
828 *
829 * @return Bush depth at this character's position
830 */
831 int GetBushDepth() const;
832
833 enum CharsID {
834 CharPlayer = 10001,
835 CharBoat = 10002,
836 CharShip = 10003,
837 CharAirship = 10004,
838 CharThisEvent = 10005
839 };
840
841 enum Direction {
842 Up = 0,
843 Right,
844 Down,
845 Left,
846 UpRight,
847 DownRight,
848 DownLeft,
849 UpLeft
850 };
851
852 static bool IsDirectionDiagonal(int d);
853
854 /** Reverses a direction, ex: ReverseDir(Up) == Down. */
855 static int ReverseDir(int dir);
856
857 static Game_Character* GetCharacter(int character_id, int event_id);
858
859 static constexpr int GetDxFromDirection(int dir);
860 static constexpr int GetDyFromDirection(int dir);
861
862 protected:
863 explicit Game_Character(Type type, lcf::rpg::SaveMapEventBase* d);
864 /** Check for and fix incorrect data after loading save game */
865 void SanitizeData(StringView name);
866 /** Check for and fix incorrect move route data after loading save game */
867 void SanitizeMoveRoute(StringView name, const lcf::rpg::MoveRoute& mr, int32_t& idx, StringView chunk_name);
868 void Update();
869 virtual void UpdateAnimation();
870 virtual void UpdateNextMovementAction() = 0;
871 virtual void UpdateMovement(int amount);
872
873 void SetMaxStopCountForStep();
874 void SetMaxStopCountForTurn();
875 void SetMaxStopCountForWait();
876 void UpdateMoveRoute(int32_t& current_index, const lcf::rpg::MoveRoute& current_route, bool is_overwrite);
877 void IncAnimCount();
878 void IncAnimFrame();
879 void UpdateFlash();
880 bool BeginMoveRouteJump(int32_t& current_index, const lcf::rpg::MoveRoute& current_route);
881
882 lcf::rpg::SaveMapEventBase* data();
883 const lcf::rpg::SaveMapEventBase* data() const;
884
885 int original_move_frequency = 2;
886 // contains if any movement (<= step_forward) of a forced move route was successful
887
888 Type _type = {};
889 lcf::rpg::SaveMapEventBase* _data = nullptr;
890 };
891
892 template <typename T>
893 class Game_CharacterDataStorage : public Game_Character
894 {
895 public:
896 using Type = Game_Character::Type;
897 Game_CharacterDataStorage(Type typ);
898
899 Game_CharacterDataStorage(const Game_CharacterDataStorage&) = delete;
900 Game_CharacterDataStorage& operator=(const Game_CharacterDataStorage&) = delete;
901
902 Game_CharacterDataStorage(Game_CharacterDataStorage&&) noexcept;
903 Game_CharacterDataStorage& operator=(Game_CharacterDataStorage&&) noexcept;
904
905 ~Game_CharacterDataStorage() = default;
906
907 T* data();
908 const T* data() const;
909 private:
910 T _data = {};
911 };
912
IsDirectionFixedAnimationType(AnimType at)913 constexpr bool Game_Character::IsDirectionFixedAnimationType(AnimType at) {
914 return
915 at == lcf::rpg::EventPage::AnimType_fixed_continuous ||
916 at == lcf::rpg::EventPage::AnimType_fixed_graphic ||
917 at == lcf::rpg::EventPage::AnimType_fixed_non_continuous;
918 }
919
data()920 inline lcf::rpg::SaveMapEventBase* Game_Character::data() {
921 return _data;
922 }
923
data()924 inline const lcf::rpg::SaveMapEventBase* Game_Character::data() const {
925 return _data;
926 }
927
GetType()928 inline Game_Character::Type Game_Character::GetType() const {
929 return _type;
930 }
931
GetX()932 inline int Game_Character::GetX() const {
933 return data()->position_x;
934 }
935
SetX(int new_x)936 inline void Game_Character::SetX(int new_x) {
937 data()->position_x = new_x;
938 }
939
GetY()940 inline int Game_Character::GetY() const {
941 return data()->position_y;
942 }
943
SetY(int new_y)944 inline void Game_Character::SetY(int new_y) {
945 data()->position_y = new_y;
946 }
947
GetMapId()948 inline int Game_Character::GetMapId() const {
949 return data()->map_id;
950 }
951
SetMapId(int new_map_id)952 inline void Game_Character::SetMapId(int new_map_id) {
953 data()->map_id = new_map_id;
954 }
955
GetDirection()956 inline int Game_Character::GetDirection() const {
957 return data()->direction;
958 }
959
SetDirection(int new_direction)960 inline void Game_Character::SetDirection(int new_direction) {
961 data()->direction = new_direction;
962 }
963
GetFacing()964 inline int Game_Character::GetFacing() const {
965 return data()->sprite_direction;
966 }
967
SetFacing(int new_direction)968 inline void Game_Character::SetFacing(int new_direction) {
969 data()->sprite_direction = new_direction;
970 }
971
IsFacingLocked()972 inline bool Game_Character::IsFacingLocked() const {
973 return data()->lock_facing;
974 }
975
SetFacingLocked(bool locked)976 inline void Game_Character::SetFacingLocked(bool locked) {
977 data()->lock_facing = locked || IsDirectionFixedAnimationType(GetAnimationType());
978 }
979
GetLayer()980 inline int Game_Character::GetLayer() const {
981 return data()->layer;
982 }
983
SetLayer(int new_layer)984 inline void Game_Character::SetLayer(int new_layer) {
985 data()->layer = new_layer;
986 }
987
IsOverlapForbidden()988 inline bool Game_Character::IsOverlapForbidden() const {
989 return data()->overlap_forbidden;
990 }
991
GetMoveSpeed()992 inline int Game_Character::GetMoveSpeed() const {
993 return data()->move_speed;
994 }
995
SetMoveSpeed(int speed)996 inline void Game_Character::SetMoveSpeed(int speed) {
997 data()->move_speed = speed;
998 }
999
GetMoveFrequency()1000 inline int Game_Character::GetMoveFrequency() const {
1001 return data()->move_frequency;
1002 }
1003
SetMoveFrequency(int frequency)1004 inline void Game_Character::SetMoveFrequency(int frequency) {
1005 data()->move_frequency = frequency;
1006 }
1007
GetMoveRoute()1008 inline const lcf::rpg::MoveRoute& Game_Character::GetMoveRoute() const {
1009 return data()->move_route;
1010 }
1011
SetMoveRoute(const lcf::rpg::MoveRoute & move_route)1012 inline void Game_Character::SetMoveRoute(const lcf::rpg::MoveRoute& move_route) {
1013 data()->move_route = move_route;
1014 }
1015
GetMoveRouteIndex()1016 inline int Game_Character::GetMoveRouteIndex() const {
1017 return data()->move_route_index;
1018 }
1019
SetMoveRouteIndex(int new_index)1020 inline void Game_Character::SetMoveRouteIndex(int new_index) {
1021 data()->move_route_index = new_index;
1022 }
1023
IsMoveRouteOverwritten()1024 inline bool Game_Character::IsMoveRouteOverwritten() const {
1025 return data()->move_route_overwrite;
1026 }
1027
SetMoveRouteOverwritten(bool force)1028 inline void Game_Character::SetMoveRouteOverwritten(bool force) {
1029 data()->move_route_overwrite = force;
1030 }
1031
IsMoveRouteRepeated()1032 inline bool Game_Character::IsMoveRouteRepeated() const {
1033 return data()->move_route_repeated;
1034 }
1035
SetMoveRouteRepeated(bool force)1036 inline void Game_Character::SetMoveRouteRepeated(bool force) {
1037 data()->move_route_repeated = force;
1038 }
1039
GetSpriteName()1040 inline const std::string& Game_Character::GetSpriteName() const {
1041 return data()->sprite_name;
1042 }
1043
SetSpriteGraphic(std::string sprite_name,int index)1044 inline void Game_Character::SetSpriteGraphic(std::string sprite_name, int index) {
1045 data()->sprite_name = std::move(sprite_name);
1046 data()->sprite_id = index;
1047 }
1048
MoveRouteSetSpriteGraphic(std::string sprite_name,int index)1049 inline void Game_Character::MoveRouteSetSpriteGraphic(std::string sprite_name, int index) {
1050 SetSpriteGraphic(std::move(sprite_name), index);
1051 }
1052
GetSpriteIndex()1053 inline int Game_Character::GetSpriteIndex() const {
1054 return data()->sprite_id;
1055 }
1056
GetAnimFrame()1057 inline int Game_Character::GetAnimFrame() const {
1058 return data()->anim_frame;
1059 }
1060
SetAnimFrame(int frame)1061 inline void Game_Character::SetAnimFrame(int frame) {
1062 data()->anim_frame = frame;
1063 }
1064
IsAnimPaused()1065 inline bool Game_Character::IsAnimPaused() const {
1066 return data()->anim_paused;
1067 }
1068
SetAnimPaused(bool value)1069 inline void Game_Character::SetAnimPaused(bool value) {
1070 data()->anim_paused = value;
1071 }
1072
GetFlashColor()1073 inline Color Game_Character::GetFlashColor() const {
1074 return Flash::MakeColor(data()->flash_red, data()->flash_green, data()->flash_blue, data()->flash_current_level);
1075 }
1076
GetFlashLevel()1077 inline double Game_Character::GetFlashLevel() const {
1078 return data()->flash_current_level;
1079 }
1080
SetFlashLevel(double flash_level)1081 inline void Game_Character::SetFlashLevel(double flash_level) {
1082 data()->flash_current_level = flash_level;
1083 }
1084
GetFlashTimeLeft()1085 inline int Game_Character::GetFlashTimeLeft() const {
1086 return data()->flash_time_left;
1087 }
1088
SetFlashTimeLeft(int time_left)1089 inline void Game_Character::SetFlashTimeLeft(int time_left) {
1090 data()->flash_time_left = time_left;
1091 }
1092
GetThrough()1093 inline bool Game_Character::GetThrough() const {
1094 return data()->through;
1095 }
1096
SetThrough(bool through)1097 inline void Game_Character::SetThrough(bool through) {
1098 data()->through = through;
1099 }
1100
ResetThrough()1101 inline void Game_Character::ResetThrough() {
1102 data()->through = data()->route_through;
1103 }
1104
GetAnimationType()1105 inline Game_Character::AnimType Game_Character::GetAnimationType() const {
1106 return AnimType(data()->animation_type);
1107 }
1108
SetAnimationType(Game_Character::AnimType anim_type)1109 inline void Game_Character::SetAnimationType(Game_Character::AnimType anim_type) {
1110 data()->animation_type = int(anim_type);
1111 SetFacingLocked(IsDirectionFixedAnimationType(anim_type));
1112 }
1113
GetStopCount()1114 inline int Game_Character::GetStopCount() const {
1115 return data()->stop_count;
1116 }
1117
SetStopCount(int sc)1118 inline void Game_Character::SetStopCount(int sc) {
1119 data()->stop_count = sc;
1120 }
1121
GetMaxStopCount()1122 inline int Game_Character::GetMaxStopCount() const {
1123 return data()->max_stop_count;
1124 }
1125
SetMaxStopCount(int sc)1126 inline void Game_Character::SetMaxStopCount(int sc) {
1127 data()->max_stop_count = sc;
1128 }
1129
IsStopCountActive()1130 inline bool Game_Character::IsStopCountActive() const {
1131 return GetStopCount() < GetMaxStopCount();
1132 }
1133
GetAnimCount()1134 inline int Game_Character::GetAnimCount() const {
1135 return data()->anim_count;
1136 }
1137
SetAnimCount(int ac)1138 inline void Game_Character::SetAnimCount(int ac) {
1139 data()->anim_count = ac;
1140 }
1141
IncAnimCount()1142 inline void Game_Character::IncAnimCount() {
1143 ++data()->anim_count;
1144 }
1145
IncAnimFrame()1146 inline void Game_Character::IncAnimFrame() {
1147 data()->anim_frame = (data()->anim_frame + 1) % 4;
1148 SetAnimCount(0);
1149 }
1150
ResetAnimation()1151 inline void Game_Character::ResetAnimation() {
1152 SetAnimCount(0);
1153 if (GetAnimationType() != lcf::rpg::EventPage::AnimType_fixed_graphic) {
1154 SetAnimFrame(lcf::rpg::EventPage::Frame_middle);
1155 }
1156 }
1157
GetRemainingStep()1158 inline int Game_Character::GetRemainingStep() const {
1159 return data()->remaining_step;
1160 }
1161
SetRemainingStep(int step)1162 inline void Game_Character::SetRemainingStep(int step) {
1163 data()->remaining_step = step;
1164 }
1165
IsJumping()1166 inline bool Game_Character::IsJumping() const {
1167 return data()->jumping;
1168 }
1169
SetJumping(bool val)1170 inline void Game_Character::SetJumping(bool val) {
1171 data()->jumping = val;
1172 }
1173
IsMoving()1174 inline bool Game_Character::IsMoving() const {
1175 return !IsJumping() && GetRemainingStep() > 0;
1176 }
1177
IsStopping()1178 inline bool Game_Character::IsStopping() const {
1179 return !(IsMoving() || IsJumping());
1180 }
1181
GetBeginJumpX()1182 inline int Game_Character::GetBeginJumpX() const {
1183 return data()->begin_jump_x;
1184 }
1185
SetBeginJumpX(int x)1186 inline void Game_Character::SetBeginJumpX(int x) {
1187 data()->begin_jump_x = x;
1188 }
1189
GetBeginJumpY()1190 inline int Game_Character::GetBeginJumpY() const {
1191 return data()->begin_jump_y;
1192 }
1193
SetBeginJumpY(int y)1194 inline void Game_Character::SetBeginJumpY(int y) {
1195 data()->begin_jump_y = y;
1196 }
1197
IsFlying()1198 inline bool Game_Character::IsFlying() const {
1199 return data()->flying;
1200 }
1201
SetFlying(bool val)1202 inline void Game_Character::SetFlying(bool val) {
1203 data()->flying = val;
1204 }
1205
GetTransparency()1206 inline int Game_Character::GetTransparency() const {
1207 return data()->transparency;
1208 }
1209
SetTransparency(int value)1210 inline void Game_Character::SetTransparency(int value) {
1211 data()->transparency = Utils::Clamp(value, 0, 7);
1212 }
1213
IsProcessed()1214 inline bool Game_Character::IsProcessed() const {
1215 return data()->processed;
1216 }
1217
SetProcessed(bool val)1218 inline void Game_Character::SetProcessed(bool val) {
1219 data()->processed = val;
1220 }
1221
IsPaused()1222 inline bool Game_Character::IsPaused() const {
1223 return data()->pause;
1224 }
1225
SetPaused(bool val)1226 inline void Game_Character::SetPaused(bool val) {
1227 data()->pause = val;
1228 }
1229
IsActive()1230 inline bool Game_Character::IsActive() const {
1231 return data()->active;
1232 }
1233
SetActive(bool active)1234 inline void Game_Character::SetActive(bool active) {
1235 data()->active = active;
1236 }
1237
HasTileSprite()1238 inline bool Game_Character::HasTileSprite() const {
1239 return GetSpriteName().empty();
1240 }
1241
GetTileId()1242 inline int Game_Character::GetTileId() const {
1243 return HasTileSprite() ? GetSpriteIndex() : 0;
1244 }
1245
SetSpriteHidden(bool hidden)1246 inline void Game_Character::SetSpriteHidden(bool hidden) {
1247 data()->sprite_transparent = hidden;
1248 }
1249
IsSpriteHidden()1250 inline bool Game_Character::IsSpriteHidden() const {
1251 return data()->sprite_transparent;
1252 }
1253
GetDirection90DegreeLeft(int dir)1254 constexpr int Game_Character::GetDirection90DegreeLeft(int dir) {
1255 return (dir + 3) % 4;
1256 }
1257
GetDirection90DegreeRight(int dir)1258 constexpr int Game_Character::GetDirection90DegreeRight(int dir) {
1259 return (dir + 1) % 4;
1260 }
1261
GetDirection180Degree(int dir)1262 constexpr int Game_Character::GetDirection180Degree(int dir) {
1263 return (dir + 2) % 4;
1264 }
1265
GetMaxStopCountForStep(int freq)1266 constexpr int Game_Character::GetMaxStopCountForStep(int freq) {
1267 return freq >= 8 ? 0 : 1 << (9 - freq);
1268 }
1269
GetMaxStopCountForTurn(int freq)1270 constexpr int Game_Character::GetMaxStopCountForTurn(int freq) {
1271 return freq >= 8 ? 0 : 1 << (8 - freq);
1272 }
1273
GetMaxStopCountForWait(int freq)1274 constexpr int Game_Character::GetMaxStopCountForWait(int freq) {
1275 return 20 + GetMaxStopCountForTurn(freq);
1276 }
1277
GetDxFromDirection(int dir)1278 constexpr int Game_Character::GetDxFromDirection(int dir) {
1279 return (dir == Game_Character::Right || dir == Game_Character::UpRight || dir == Game_Character::DownRight)
1280 - (dir == Game_Character::Left || dir == Game_Character::DownLeft || dir == Game_Character::UpLeft);
1281 }
1282
GetDyFromDirection(int dir)1283 constexpr int Game_Character::GetDyFromDirection(int dir) {
1284 return (dir == Game_Character::Down || dir == Game_Character::DownRight || dir == Game_Character::DownLeft)
1285 - (dir == Game_Character::Up || dir == Game_Character::UpRight || dir == Game_Character::UpLeft);
1286 }
1287
GetStationaryAnimFrames(int speed)1288 constexpr int Game_Character::GetStationaryAnimFrames(int speed) {
1289 constexpr int limits[] = { 12, 10, 8, 6, 5, 4 };
1290 return limits[speed - 1];
1291 }
1292
GetContinuousAnimFrames(int speed)1293 constexpr int Game_Character::GetContinuousAnimFrames(int speed) {
1294 constexpr int limits[] = { 16, 12, 10, 8, 7, 6 };
1295 return limits[speed - 1];
1296 }
1297
GetSpinAnimFrames(int speed)1298 constexpr int Game_Character::GetSpinAnimFrames(int speed) {
1299 constexpr int limits[] = { 24, 16, 12, 8, 6, 4 };
1300 return limits[speed - 1];
1301 }
1302
IsVisible()1303 inline bool Game_Character::IsVisible() const {
1304 return IsActive() && !IsSpriteHidden() && GetOpacity() > 0;
1305 }
1306
1307 template <typename T>
Game_CharacterDataStorage(Type typ)1308 inline Game_CharacterDataStorage<T>::Game_CharacterDataStorage(Type typ)
1309 : Game_Character(typ, nullptr)
1310 {
1311 Game_Character::_data = &this->_data;
1312 }
1313
1314 template <typename T>
Game_CharacterDataStorage(Game_CharacterDataStorage && o)1315 inline Game_CharacterDataStorage<T>::Game_CharacterDataStorage(Game_CharacterDataStorage&& o) noexcept
1316 : Game_Character(std::move(o)), _data(std::move(o._data))
1317 {
1318 Game_Character::_data = &this->_data;
1319 }
1320
1321 template <typename T>
1322 inline Game_CharacterDataStorage<T>& Game_CharacterDataStorage<T>::operator=(Game_CharacterDataStorage&& o) noexcept
1323 {
1324 static_cast<Game_Character*>(this) = std::move(o);
1325 if (this != &o) {
1326 _data = std::move(o._data);
1327 Game_Character::_data = &this->_data;
1328 }
1329 return *this;
1330 }
1331
1332 template <typename T>
data()1333 inline T* Game_CharacterDataStorage<T>::data() {
1334 return static_cast<T*>(Game_Character::data());
1335 }
1336
1337 template <typename T>
data()1338 inline const T* Game_CharacterDataStorage<T>::data() const {
1339 return static_cast<const T*>(Game_Character::data());
1340 }
1341
IsDirectionDiagonal(int d)1342 inline bool Game_Character::IsDirectionDiagonal(int d) {
1343 return d >= UpRight;
1344 }
1345
TypeToStr(Game_Character::Type type)1346 inline StringView Game_Character::TypeToStr(Game_Character::Type type) {
1347 switch (type) {
1348 case Player: return "Player";
1349 case Vehicle: return "Vehicle";
1350 case Event: return "Event";
1351 }
1352 return "UnknownCharacter";
1353 }
1354
1355 #endif
1356