ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/common/anim.C
(Generate patch)

Comparing deliantra/server/common/anim.C (file contents):
Revision 1.1 by elmex, Sun Aug 13 17:16:00 2006 UTC vs.
Revision 1.16 by root, Sun Jan 14 23:15:57 2007 UTC

1/*
2 * static char *rcsid_anim_c =
3 * "$Id: anim.C,v 1.1 2006/08/13 17:16:00 elmex Exp $";
4 */
5
6/* 1/*
7 CrossFire, A Multiplayer game for X-windows 2 CrossFire, A Multiplayer game for X-windows
8 3
4 Copyright (C) 2005, 2006, 2007 Marc Lehmann & Crossfire+ Development Team
9 Copyright (C) 2002-2003 Mark Wedel & Crossfire Development Team 5 Copyright (C) 2002-2003 Mark Wedel & Crossfire Development Team
10 Copyright (C) 1992 Frank Tore Johansen 6 Copyright (C) 1992 Frank Tore Johansen
11 7
12 This program is free software; you can redistribute it and/or modify 8 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by 9 it under the terms of the GNU General Public License as published by
21 17
22 You should have received a copy of the GNU General Public License 18 You should have received a copy of the GNU General Public License
23 along with this program; if not, write to the Free Software 19 along with this program; if not, write to the Free Software
24 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 21
26 The authors can be reached via e-mail at crossfire-devel@real-time.com 22 The authors can be reached via e-mail at <crossfire@schmorp.de>
27*/ 23*/
28 24
29/* This file contains animation related code. */ 25/* This file contains animation related code. */
30 26
31#include <global.h> 27#include <global.h>
32#include <stdio.h> 28#include <stdio.h>
33 29
30void
34void free_all_anim(void) { 31free_all_anim (void)
35 int i; 32{
36
37 for (i=0; i<=num_animations; i++) { 33 for (int i = 0; i <= num_animations; i++)
38 free_string(animations[i].name); 34 {
35 animations[i].name = 0;
39 free(animations[i].faces); 36 free (animations[i].faces);
40 } 37 }
41 free(animations);
42}
43 38
39 animations.clear ();
40}
41
42void
44void init_anim(void) { 43init_anim (void)
44{
45 char
45 char buf[MAX_BUF]; 46 buf[MAX_BUF];
46 FILE *fp; 47 FILE *
47 static int anim_init=0; 48 fp;
49 static int
50 anim_init = 0;
51 int
48 int num_frames=0,faces[MAX_ANIMATIONS],i; 52 num_frames = 0, faces[MAX_ANIMATIONS], i;
49 53
50 if (anim_init) return; 54 if (anim_init)
51 animations_allocated=9; 55 return;
52 num_animations=0; 56 num_animations = 0;
53 /* Make a default. New animations start at one, so if something 57 /* Make a default. New animations start at one, so if something
54 * thinks it is animated but hasn't set the animation_id properly, 58 * thinks it is animated but hasn't set the animation_id properly,
55 * it will have a default value that should be pretty obvious. 59 * it will have a default value that should be pretty obvious.
56 */ 60 */
57 animations = (Animations *) malloc(10*sizeof(Animations));
58 /* set the name so we don't try to dereferance null. 61 /* set the name so we don't try to dereferance null.
59 * Put # at start so it will be first in alphabetical 62 * Put # at start so it will be first in alphabetical
60 * order. 63 * order.
61 */ 64 */
62 animations[0].name=add_string("###none"); 65 {
66 Animations anim0;
67
68 anim0.name = "###none";
63 animations[0].num_animations=1; 69 anim0.num_animations = 1;
64 animations[0].faces = (Fontindex *) malloc(sizeof(Fontindex)); 70 anim0.faces = (uint16 *)malloc (sizeof (uint16));
65 animations[0].faces[0]=0; 71 anim0.faces[0] = 0;
66 animations[0].facings=0; 72 anim0.facings = 0;
67 73
74 animations.push_back (anim0);
75 }
76
68 sprintf(buf,"%s/animations", settings.datadir); 77 sprintf (buf, "%s/animations", settings.datadir);
69 LOG(llevDebug,"Reading animations from %s...", buf); 78 LOG (llevDebug, "Reading animations from %s...\n", buf);
70 if ((fp=fopen(buf,"r")) ==NULL) { 79 if ((fp = fopen (buf, "r")) == NULL)
80 {
71 LOG(llevError, "Cannot open animations file %s: %s\n", buf, strerror_local(errno)); 81 LOG (llevError, "Cannot open animations file %s: %s\n", buf, strerror (errno));
72 exit(-1); 82 exit (-1);
73 }
74 while (fgets(buf, MAX_BUF-1, fp)!=NULL) {
75 if (*buf=='#') continue;
76 /* Kill the newline */
77 buf[strlen(buf)-1] = '\0';
78 if (!strncmp(buf,"anim ", 5)) {
79 if (num_frames) {
80 LOG(llevError,"Didn't get a mina before %s\n", buf);
81 num_frames=0;
82 } 83 }
84 while (fgets (buf, MAX_BUF - 1, fp) != NULL)
85 {
86 if (*buf == '#')
87 continue;
88 /* Kill the newline */
89 buf[strlen (buf) - 1] = '\0';
90 if (!strncmp (buf, "anim ", 5))
91 {
92 if (num_frames)
93 {
94 LOG (llevError, "Didn't get a mina before %s\n", buf);
95 num_frames = 0;
96 }
83 num_animations++; 97 num_animations++;
84 if (num_animations==animations_allocated) { 98
85 animations= (Animations *) realloc(animations, sizeof(Animations)*(animations_allocated+10)); 99 Animations anim;
86 animations_allocated+=10; 100
87 } 101 anim.name = buf + 5;
88 animations[num_animations].name = add_string(buf+5); 102 anim.num = num_animations; /* for bsearch */
89 animations[num_animations].num = num_animations; /* for bsearch */ 103 anim.facings = 1;
90 animations[num_animations].facings = 1; 104 animations.push_back (anim);
91 } 105 }
92 else if (!strncmp(buf,"mina",4)) { 106 else if (!strncmp (buf, "mina", 4))
107 {
93 animations[num_animations].faces = (Fontindex *) malloc(sizeof(Fontindex)*num_frames); 108 animations[num_animations].faces = (uint16 *) malloc (sizeof (uint16) * num_frames);
94 for (i=0; i<num_frames; i++) 109 for (i = 0; i < num_frames; i++)
95 animations[num_animations].faces[i]=faces[i]; 110 animations[num_animations].faces[i] = faces[i];
96 animations[num_animations].num_animations = num_frames; 111 animations[num_animations].num_animations = num_frames;
97 if (num_frames % animations[num_animations].facings) { 112 if (num_frames % animations[num_animations].facings)
113 {
98 LOG(llevDebug,"Animation %s frame numbers (%d) is not a multiple of facings (%d)\n", 114 LOG (llevDebug, "Animation %s frame numbers (%d) is not a multiple of facings (%d)\n",
99 animations[num_animations].name, num_frames, animations[num_animations].facings); 115 &animations[num_animations].name, num_frames, animations[num_animations].facings);
100 } 116 }
101 num_frames=0; 117 num_frames = 0;
102 } 118 }
103 else if (!strncmp(buf,"facings",7)) { 119 else if (!strncmp (buf, "facings", 7))
120 {
104 if (!(animations[num_animations].facings = atoi(buf+7))) { 121 if (!(animations[num_animations].facings = atoi (buf + 7)))
105 LOG(llevDebug,"Animation %s has 0 facings, line=%s\n", 122 {
106 animations[num_animations].name, buf); 123 LOG (llevDebug, "Animation %s has 0 facings, line=%s\n", &animations[num_animations].name, buf);
107 animations[num_animations].facings=1; 124 animations[num_animations].facings = 1;
108 } 125 }
109 126
110 } else { 127 }
128 else
129 {
111 if (!(faces[num_frames++] = FindFace(buf,0))) 130 if (!(faces[num_frames++] = FindFace (buf, 0)))
112 LOG(llevDebug,"Could not find face %s for animation %s\n", 131 LOG (llevDebug, "Could not find face %s for animation %s\n", buf, &animations[num_animations].name);
113 buf, animations[num_animations].name); 132 }
114 }
115 } 133 }
116 fclose(fp); 134 fclose (fp);
117 LOG(llevDebug,"done. got (%d)\n", num_animations); 135 LOG (llevDebug, "done. got (%d)\n", num_animations);
118} 136}
119 137
138static int
120static int anim_compare(const Animations *a, const Animations *b) { 139anim_compare (const Animations * a, const Animations * b)
140{
121 return strcmp(a->name, b->name); 141 return strcmp (a->name, b->name);
122} 142}
123 143
124/* Tries to find the animation id that matches name. Returns an integer match 144/* Tries to find the animation id that matches name. Returns an integer match
125 * 0 if no match found (animation 0 is initialized as the 'bug' face 145 * 0 if no match found (animation 0 is initialised as the 'bug' face
126 */ 146 */
147int
127int find_animation(const char *name) 148find_animation (const char *name)
128{ 149{
129 Animations search, *match; 150 Animations search, *match;
130 151
131 search.name = name; 152 search.name = name;
132 153
133 match = (Animations*)bsearch(&search, animations, (num_animations+1), 154 match = (Animations *) bsearch (&search, &animations[0], (num_animations + 1),
134 sizeof(Animations), (int (*)(const void*, const void*))anim_compare); 155 sizeof (Animations), (int (*)(const void *, const void *)) anim_compare);
135 156
136 157
158 if (match)
137 if (match) return match->num; 159 return match->num;
160
138 LOG(llevError,"Unable to find animation %s\n", name); 161 LOG (llevError, "Unable to find animation %s\n", name);
162
139 return 0; 163 return 0;
140} 164}
141 165
142/* 166/*
143 * animate_object(object) updates the face-variable of an object. 167 * animate_object(object) updates the face-variable of an object.
144 * If the object is the head of a multi-object, all objects are animated. 168 * If the object is the head of a multi-object, all objects are animated.
146 * dir is the direction the object is facing. This is generally same as 170 * dir is the direction the object is facing. This is generally same as
147 * op->direction, but in some cases, op->facing is used instead - the 171 * op->direction, but in some cases, op->facing is used instead - the
148 * caller has a better idea which one it really wants to be using, 172 * caller has a better idea which one it really wants to be using,
149 * so let it pass along the right one. 173 * so let it pass along the right one.
150 */ 174 */
151 175void
152void animate_object(object *op, int dir) { 176animate_object (object *op, int dir)
177{
153 int max_state; /* Max animation state object should be drawn in */ 178 int max_state; /* Max animation state object should be drawn in */
154 int base_state; /* starting index # to draw from */ 179 int base_state; /* starting index # to draw from */
155 180
156 if(!op->animation_id || !NUM_ANIMATIONS(op)) { 181 if (!op->animation_id || !NUM_ANIMATIONS (op))
157 LOG(llevError,"Object lacks animation.\n");
158 dump_object(op);
159 return;
160 } 182 {
183 LOG (llevError, "Object %s lacks animation.\n", op->debug_desc ());
184 CLEAR_FLAG (op, FLAG_ANIMATE);
185 return;
186 }
187
161 if (op->head) { 188 if (op->head)
189 {
162 dir=op->head->direction; 190 dir = op->head->direction;
163 191
164 if (NUM_ANIMATIONS(op) == NUM_ANIMATIONS(op->head)) 192 if (NUM_ANIMATIONS (op) == NUM_ANIMATIONS (op->head))
165 op->state = op->head->state; 193 op->state = op->head->state;
166 else 194 else
167 ++op->state; 195 ++op->state;
168 } 196 }
169 else { 197 else
170 ++op->state; /* increase draw state */ 198 ++op->state; /* increase draw state */
171 }
172 199
173 /* If object is turning, then max animation state is half through the 200 /* If object is turning, then max animation state is half through the
174 * animations. Otherwise, we can use all the animations. 201 * animations. Otherwise, we can use all the animations.
175 */ 202 */
176 max_state=NUM_ANIMATIONS(op)/ NUM_FACINGS(op); 203 max_state = NUM_ANIMATIONS (op) / NUM_FACINGS (op);
177 base_state=0; 204 base_state = 0;
178 /* at least in the older aniamtions that used is_turning, the first half 205 /* at least in the older aniamtions that used is_turning, the first half
179 * of the animations were left facing, the second half right facing. 206 * of the animations were left facing, the second half right facing.
180 * Note in old the is_turning, it was set so that the animation for a monster 207 * Note in old the is_turning, it was set so that the animation for a monster
181 * was always towards the enemy - now it is whatever direction the monster 208 * was always towards the enemy - now it is whatever direction the monster
182 * is facing. 209 * is facing.
183 */ 210 */
211
184 if (NUM_FACINGS(op)==2) { 212 if (NUM_FACINGS (op) == 2)
185 if (dir<5) base_state=0;
186 else base_state=NUM_ANIMATIONS(op)/2;
187 } 213 {
214 if (dir < 5)
215 base_state = 0;
216 else
217 base_state = NUM_ANIMATIONS (op) / 2;
218 }
188 else if (NUM_FACINGS(op)==4) { 219 else if (NUM_FACINGS (op) == 4)
189 if (dir==0) base_state=0; 220 {
221 if (dir == 0)
222 base_state = 0;
223 else
190 else base_state = ((dir-1)/2) * (NUM_ANIMATIONS(op)/4); 224 base_state = ((dir - 1) / 2) * (NUM_ANIMATIONS (op) / 4);
191 } 225 }
192 else if (NUM_FACINGS(op)==8) { 226 else if (NUM_FACINGS (op) == 8)
193 if (dir==0) base_state=0; 227 {
228 if (dir == 0)
229 base_state = 0;
230 else
194 else base_state = (dir-1)*(NUM_ANIMATIONS(op)/8); 231 base_state = (dir - 1) * (NUM_ANIMATIONS (op) / 8);
195 } 232 }
196 233
197 /* If beyond drawable states, reset */ 234 /* If beyond drawable states, reset */
198 if (op->state>=max_state) op->state=0; 235 if (op->state >= max_state)
236 op->state = 0;
199 237
200 SET_ANIMATION(op, op->state + base_state); 238 SET_ANIMATION (op, op->state + base_state);
201 239
202 if(op->face==blank_face) 240 if (op->face == blank_face)
203 op->invisible=1; 241 op->invisible = 1;
204 242
205 /* This block covers monsters (eg, pixies) which are supposed to 243 /* This block covers monsters (eg, pixies) which are supposed to
206 * cycle from visible to invisible and back to being visible. 244 * cycle from visible to invisible and back to being visible.
207 * as such, disable it for players, as then players would become 245 * as such, disable it for players, as then players would become
208 * visible. 246 * visible.
209 */ 247 */
210 else if(op->type != PLAYER && QUERY_FLAG((&op->arch->clone),FLAG_ALIVE)) { 248 else if (op->type != PLAYER && QUERY_FLAG ((&op->arch->clone), FLAG_ALIVE))
249 {
211 if(op->face->number==0) { 250 if (op->face->number == 0)
251 {
212 op->invisible=1; 252 op->invisible = 1;
213 CLEAR_FLAG(op, FLAG_ALIVE); 253 CLEAR_FLAG (op, FLAG_ALIVE);
214 } else { 254 }
255 else
256 {
215 op->invisible=0; 257 op->invisible = 0;
216 SET_FLAG(op, FLAG_ALIVE); 258 SET_FLAG (op, FLAG_ALIVE);
217 } 259 }
218 } 260 }
219 261
220 if(op->more) 262 if (op->more)
221 animate_object(op->more, dir); 263 animate_object (op->more, dir);
222 264
223 /* update_object will also recursively update all the pieces. 265 /* update_object will also recursively update all the pieces.
224 * as such, we call it last, and only call it for the head 266 * as such, we call it last, and only call it for the head
225 * piece, and not for the other tail pieces. 267 * piece, and not for the other tail pieces.
226 */ 268 */
227 if (!op->head) 269 if (!op->head)
228 update_object(op, UP_OBJ_FACE); 270 update_object (op, UP_OBJ_FACE);
229} 271}
230

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines