1 /* ScummVM - Graphic Adventure Engine
2  *
3  * ScummVM is the legal property of its developers, whose names
4  * are too numerous to list here. Please refer to the COPYRIGHT
5  * file distributed with this source distribution.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20  *
21  */
22 
23 #ifndef WORLD_ACTORS_ANIMACTION_H
24 #define WORLD_ACTORS_ANIMACTION_H
25 
26 #include "ultima/shared/std/containers.h"
27 #include "ultima/ultima8/misc/direction.h"
28 
29 namespace Ultima {
30 namespace Ultima8 {
31 
32 class Actor;
33 
34 struct AnimFrame {
35 	int _frame;
36 	int _deltaZ;
37 	int _deltaDir;
38 	int _sfx;
39 	uint32 _flags;
40 
41 	/** Frame level flags */
42 	enum AnimFrameFlags {
43 		AFF_ONGROUND = 0x00000002,
44 		AFF_FLIPPED  = 0x00000020,
45 		AFF_SPECIAL  = 0x00000800, // U8 only
46 		AFF_HURTY    = 0x00001000, // Crusader only - TODO: find a better name for this.
47 		AFF_USECODE  = 0x00004000,
48 		AFF_CRUFLIP  = 0x00008000  // Crusader only
49 		//AFF_UNKNOWN  = 0xF0E0B01C,
50 		//AFF_FIRE     = 0x0F1F00C0
51 	};
52 
is_ongroundAnimFrame53 	inline bool is_onground() const {
54 		return (_flags & AFF_ONGROUND) != 0;
55 	}
56 
is_flippedAnimFrame57 	inline bool is_flipped() const {
58 		return (_flags & AFF_FLIPPED) != 0;
59 	}
60 
is_callusecodeAnimFrame61 	inline bool is_callusecode() const {
62 		return (_flags & AFF_USECODE) != 0;
63 	}
64 
is_cruflippedAnimFrame65 	inline bool is_cruflipped() const {
66 		return (_flags & AFF_CRUFLIP) != 0;
67 	}
68 
attack_rangeAnimFrame69 	inline int attack_range() const {
70 		return ((_flags >> 2) & 0x07);
71 	}
72 
73 	// Note: The next 3 functions each have a 4-bit
74 	// value to unpack from the flags. x/y are signed, z is unsigned.
cru_attackxAnimFrame75 	inline int cru_attackx() const {
76 		uint32 rawx = (_flags & 0x00000780) << 5;
77 		int16  signedx = static_cast<int16>(rawx) >> 12;
78 		return signedx * 16;
79 	}
80 
cru_attackyAnimFrame81 	inline int cru_attacky() const {
82 		uint32 rawy = (_flags & 0x00F00000) >> 16;
83 		return static_cast<int8>(rawy);
84 	}
85 
cru_attackzAnimFrame86 	inline int cru_attackz() const {
87 		return (_flags & 0x0F000000) >> 21;
88 	}
89 
is_cruattackAnimFrame90 	inline bool is_cruattack() const {
91 		return (cru_attackx() || cru_attacky() || cru_attackz());
92 	}
93 };
94 
95 class AnimAction {
96 	friend class AnimDat;
97 
98 public:
99 	//! return the range of the animation to play
100 	//! \param actor The actor to play the animation for
101 	//! \param dir The direction
102 	//! \param startframe The first frame to play
103 	//! \param endframe The frame after the last frame to play
104 	void getAnimRange(const Actor *actor, Direction dir,
105 	                  unsigned int &startframe, unsigned int &endframe) const;
106 
107 	//! return the range of the animation to play
108 	//! \param lastanim The lastanim of the Actor
109 	//! \param lastdir The direction of the Actor
110 	//! \param firststep The firststep flag of the Actor
111 	//! \param dir The direction
112 	//! \param startframe The first frame to play
113 	//! \param endframe The frame after the last frame to play
114 	void getAnimRange(unsigned int lastanim, Direction lastdir,
115 	                  bool firststep, Direction dir,
116 	                  unsigned int &startframe, unsigned int &endframe) const;
117 
getDirCount()118 	unsigned int getDirCount() const {
119 		return _dirCount;
120 	}
121 
getSize()122 	unsigned int getSize() const {
123 		return _size;
124 	}
125 
getFrameRepeat()126 	int getFrameRepeat() const {
127 		return _frameRepeat;
128 	}
129 
getShapeNum()130 	uint32 getShapeNum() const {
131 		return _shapeNum;
132 	}
133 
getAction()134 	uint32 getAction() const {
135 		return _action;
136 	}
137 
hasFlags(uint32 mask)138 	bool hasFlags(uint32 mask) const {
139 		return (_flags & mask) != 0;
140 	}
141 
getFlags()142 	uint32 getFlags() const {
143 		return _flags;
144 	}
145 
146 	const AnimFrame &getFrame(Direction dir, unsigned int frameno) const;
147 
148 	/**
149 	 * Animation level flags
150 	 *
151 	 * Note: Although these match the original values in the dat files, there is cleanup
152 	 * at load time to avoid having to check game type in many places in the code.
153 	 * See loadAnimActionFlags in anim_action.cpp
154 	 */
155 	enum AnimActionFlags {
156 		AAF_NONE		 = 0x0000,
157 		AAF_TWOSTEP      = 0x0001,
158 		AAF_ATTACK       = 0x0002, // U8 only? also present in crusader, but ignored.
159 		AAF_LOOPING      = 0x0004,
160 		AAF_UNSTOPPABLE  = 0x0008,
161 		AAF_LOOPING2_U8  = 0x0010,
162 		AAF_ENDLOOP_U8   = 0x0020, // TODO: This starts a new anim at the end if pathfinding
163 		AAF_ENDLOOP_CRU  = 0x0040, // TODO: This starts a new anim at the end if pathfinding
164 		AAF_HANGING      = 0x0080,
165 		AAF_16DIRS       = 0x4000, // Cru only
166 		AAF_DESTROYACTOR = 0x8000, // destroy actor after animation finishes
167 		AAF_ROTATED     = 0x10000, // Cru only
168 		AAF_COMMONFLAGS  = (AAF_TWOSTEP | AAF_LOOPING | AAF_UNSTOPPABLE | AAF_HANGING | AAF_DESTROYACTOR)
169 	};
170 
171 
172 private:
173 	static AnimActionFlags loadAnimActionFlags(uint32 rawflags);
174 
175 	uint32 _shapeNum;
176 	uint32 _action;
177 
178 	Std::vector<AnimFrame> _frames[16]; // 8 or 16 directions
179 	unsigned int _size;
180 	int _frameRepeat;
181 	AnimActionFlags _flags;
182 
183 	unsigned int _dirCount;
184 };
185 
186 } // End of namespace Ultima8
187 } // End of namespace Ultima
188 
189 #endif
190