--- deliantra/server/common/anim.C 2006/09/11 20:28:37 1.8
+++ deliantra/server/common/anim.C 2008/05/06 16:55:25 1.30
@@ -1,173 +1,87 @@
-
/*
- * static char *rcsid_anim_c =
- * "$Id: anim.C,v 1.8 2006/09/11 20:28:37 root Exp $";
+ * This file is part of Deliantra, the Roguelike Realtime MMORPG.
+ *
+ * Copyright (©) 2005,2006,2007,2008 Marc Alexander Lehmann / Robin Redeker / the Deliantra team
+ * Copyright (©) 2002-2003,2007 Mark Wedel & Crossfire Development Team
+ * Copyright (©) 1992,2007 Frank Tore Johansen
+ *
+ * Deliantra is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ * The authors can be reached via e-mail to
*/
-/*
- CrossFire, A Multiplayer game for X-windows
-
- Copyright (C) 2002-2003 Mark Wedel & Crossfire Development Team
- Copyright (C) 1992 Frank Tore Johansen
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
- The authors can be reached via e-mail at crossfire-devel@real-time.com
-*/
-
/* This file contains animation related code. */
#include
#include
-std::vector < Animations > animations;
+animhash_t animhash;
+std::vector animations;
void
-free_all_anim (void)
+animation::resize (int new_size)
{
- for (int i = 0; i <= num_animations; i++)
- {
- animations[i].name = 0;
- free (animations[i].faces);
- }
-
- animations.clear ();
+ sfree (faces, num_animations);
+ num_animations = new_size;
+ faces = salloc (num_animations);
}
-void
-init_anim (void)
+animation &
+animation::create (const char *name, uint8 frames, uint8 facings)
{
- char
- buf[MAX_BUF];
- FILE *
- fp;
- static int
- anim_init = 0;
- int
- num_frames = 0, faces[MAX_ANIMATIONS], i;
-
- if (anim_init)
- return;
- num_animations = 0;
- /* Make a default. New animations start at one, so if something
- * thinks it is animated but hasn't set the animation_id properly,
- * it will have a default value that should be pretty obvious.
- */
- /* set the name so we don't try to dereferance null.
- * Put # at start so it will be first in alphabetical
- * order.
- */
- {
- Animations anim0;
+ if (animations.size () == MAXANIMNUM)
+ cleanup ("trying to create new animation, but MAXANIMNUM animations in use.");
- anim0.name = "###none";
- anim0.num_animations = 1;
- anim0.faces = (Fontindex *) malloc (sizeof (Fontindex));
- anim0.faces[0] = 0;
- anim0.facings = 0;
-
- animations.push_back (anim0);
- }
-
- sprintf (buf, "%s/animations", settings.datadir);
- LOG (llevDebug, "Reading animations from %s...", buf);
- if ((fp = fopen (buf, "r")) == NULL)
- {
- LOG (llevError, "Cannot open animations file %s: %s\n", buf, strerror (errno));
- exit (-1);
- }
- while (fgets (buf, MAX_BUF - 1, fp) != NULL)
- {
- if (*buf == '#')
- continue;
- /* Kill the newline */
- buf[strlen (buf) - 1] = '\0';
- if (!strncmp (buf, "anim ", 5))
- {
- if (num_frames)
- {
- LOG (llevError, "Didn't get a mina before %s\n", buf);
- num_frames = 0;
- }
- num_animations++;
-
- Animations anim;
-
- anim.name = buf + 5;
- anim.num = num_animations; /* for bsearch */
- anim.facings = 1;
- animations.push_back (anim);
- }
- else if (!strncmp (buf, "mina", 4))
- {
- animations[num_animations].faces = (Fontindex *) malloc (sizeof (Fontindex) * num_frames);
- for (i = 0; i < num_frames; i++)
- animations[num_animations].faces[i] = faces[i];
- animations[num_animations].num_animations = num_frames;
- if (num_frames % animations[num_animations].facings)
- {
- LOG (llevDebug, "Animation %s frame numbers (%d) is not a multiple of facings (%d)\n",
- &animations[num_animations].name, num_frames, animations[num_animations].facings);
- }
- num_frames = 0;
- }
- else if (!strncmp (buf, "facings", 7))
- {
- if (!(animations[num_animations].facings = atoi (buf + 7)))
- {
- LOG (llevDebug, "Animation %s has 0 facings, line=%s\n", &animations[num_animations].name, buf);
- animations[num_animations].facings = 1;
- }
+ animations.push_back (animation ());
+ animation &anim = animations.back ();
- }
- else
- {
- if (!(faces[num_frames++] = FindFace (buf, 0)))
- LOG (llevDebug, "Could not find face %s for animation %s\n", buf, &animations[num_animations].name);
- }
- }
- fclose (fp);
- LOG (llevDebug, "done. got (%d)\n", num_animations);
+ anim.number = animations.size () - 1;
+ anim.name = name;
+ anim.num_animations = frames;
+ anim.facings = facings;
+ anim.faces = salloc (frames);
+
+ animhash.insert (std::make_pair (anim.name, anim.number));
+
+ return anim;
}
-static int
-anim_compare (const Animations * a, const Animations * b)
+animation &
+animation::find (const char *name)
+{
+ if (!name)
+ return animations [0];
+
+ animhash_t::iterator i = animhash.find (name);
+ return animations [i == animhash.end () ? 0 : i->second];
+}
+
+void
+init_anim (void)
{
- return strcmp (a->name, b->name);
+ animation &anim0 = animation::create ("none", 1, 0);
+ anim0.faces [0] = 0;
}
/* Tries to find the animation id that matches name. Returns an integer match
- * 0 if no match found (animation 0 is initialized as the 'bug' face
+ * 0 if no match found (animation 0 is initialised as the 'bug' face
*/
+//TODO: nuke this function and replace all occurences by animations::find
int
find_animation (const char *name)
{
- Animations
- search, *
- match;
-
- search.name = name;
-
- match = (Animations *) bsearch (&search, &animations[0], (num_animations + 1),
- sizeof (Animations), (int (*)(const void *, const void *)) anim_compare);
-
-
- if (match)
- return match->num;
- LOG (llevError, "Unable to find animation %s\n", name);
- return 0;
+ return animation::find (name).number;
}
/*
@@ -179,22 +93,20 @@
* caller has a better idea which one it really wants to be using,
* so let it pass along the right one.
*/
-
void
animate_object (object *op, int dir)
{
- int
- max_state; /* Max animation state object should be drawn in */
- int
- base_state; /* starting index # to draw from */
+ int max_state; /* Max animation state object should be drawn in */
+ int base_state; /* starting index # to draw from */
if (!op->animation_id || !NUM_ANIMATIONS (op))
{
- LOG (llevError, "Object lacks animation.\n");
- dump_object (op);
+ LOG (llevError, "Object %s lacks animation.\n", op->debug_desc ());
+ CLEAR_FLAG (op, FLAG_ANIMATE);
return;
}
- if (op->head)
+
+ if (op->head_ () != op)
{
dir = op->head->direction;
@@ -204,21 +116,20 @@
++op->state;
}
else
- {
- ++op->state; /* increase draw state */
- }
+ ++op->state; /* increase draw state */
/* If object is turning, then max animation state is half through the
* animations. Otherwise, we can use all the animations.
*/
max_state = NUM_ANIMATIONS (op) / NUM_FACINGS (op);
base_state = 0;
- /* at least in the older aniamtions that used is_turning, the first half
+ /* at least in the older animations that used is_turning, the first half
* of the animations were left facing, the second half right facing.
* Note in old the is_turning, it was set so that the animation for a monster
* was always towards the enemy - now it is whatever direction the monster
* is facing.
*/
+
if (NUM_FACINGS (op) == 2)
{
if (dir < 5)
@@ -255,9 +166,9 @@
* as such, disable it for players, as then players would become
* visible.
*/
- else if (op->type != PLAYER && QUERY_FLAG ((&op->arch->clone), FLAG_ALIVE))
+ else if (op->type != PLAYER && op->arch->flag [FLAG_ALIVE])
{
- if (op->face->number == 0)
+ if (op->face == 0)
{
op->invisible = 1;
CLEAR_FLAG (op, FLAG_ALIVE);
@@ -276,6 +187,7 @@
* as such, we call it last, and only call it for the head
* piece, and not for the other tail pieces.
*/
- if (!op->head)
+ if (op->head_ () == op)
update_object (op, UP_OBJ_FACE);
}
+