--- deliantra/server/common/player.C 2006/08/13 17:16:00 1.1
+++ deliantra/server/common/player.C 2007/09/04 05:43:21 1.34
@@ -1,70 +1,41 @@
/*
- * static char *rcsid_player_c =
- * "$Id: player.C,v 1.1 2006/08/13 17:16:00 elmex Exp $";
+ * This file is part of Crossfire TRT, the Roguelike Realtime MORPG.
+ *
+ * Copyright (©) 2005,2006,2007 Marc Alexander Lehmann / Robin Redeker / the Crossfire TRT team
+ * Copyright (©) 2002,2007 Mark Wedel & Crossfire Development Team
+ * Copyright (©) 1992,2007 Frank Tore Johansen
+ *
+ * Crossfire TRT 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 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
-*/
-
#include
#include
-void free_player(player *pl) {
-
- if (first_player!=pl) {
- player *prev=first_player;
- while(prev!=NULL&&prev->next!=NULL&&prev->next!=pl)
- prev=prev->next;
- if(prev->next!=pl) {
- LOG(llevError,"Free_player: Can't find previous player.\n");
- exit(1);
- }
- prev->next=pl->next;
- } else first_player=pl->next;
-
- if(pl->ob != NULL) {
- if (!QUERY_FLAG(pl->ob, FLAG_REMOVED)) remove_ob(pl->ob);
- free_object(pl->ob);
- }
- /* Clear item stack */
- if (pl->stack_items) free( pl->stack_items );
-
- free(pl->socket.faces_sent);
-
- CFREE(pl);
-}
-
-
/* Determine if the attacktype represented by the
* specified attack-number is enabled for dragon players.
* A dragon player (quetzal) can gain resistances for
* all enabled attacktypes.
*/
-int atnr_is_dragon_enabled(int attacknr) {
+int
+atnr_is_dragon_enabled (int attacknr)
+{
if (attacknr == ATNR_MAGIC || attacknr == ATNR_FIRE ||
- attacknr == ATNR_ELECTRICITY || attacknr == ATNR_COLD ||
- attacknr == ATNR_ACID || attacknr == ATNR_POISON)
+ attacknr == ATNR_ELECTRICITY || attacknr == ATNR_COLD || attacknr == ATNR_ACID || attacknr == ATNR_POISON)
return 1;
+
return 0;
}
@@ -72,10 +43,228 @@
* returns true if the adressed object 'ob' is a player
* of the dragon race.
*/
-int is_dragon_pl(const object* op) {
- if (op != NULL && op->type == PLAYER && op->arch != NULL
- && op->arch->clone.race != NULL &&
- strcmp(op->arch->clone.race, "dragon")==0)
+int
+is_dragon_pl (const object *op)
+{
+ if (op
+ && op->type == PLAYER
+ && op->arch
+ && op->arch->race
+ && !strcmp (op->arch->race, "dragon"))
return 1;
+
+ return 0;
+}
+
+/*
+ * If final is set, it a clean/final save, not a backup, ie dont remove objects from inventory
+ */
+bool
+player::save_pl (object_freezer &freezer)
+{
+ INVOKE_PLAYER (SAVE, ob->contr);
+
+ int wiz = ob->flag [FLAG_WIZ];
+
+ /* Eneq(@csd.uu.se): If we have an open container hide it. */
+ object *container = ob->container;
+ ob->container = 0;
+
+ if (ob->map)
+ maplevel = ob->map->path;
+
+#define PL_OUT(k) freezer.put (KW_ ## k, k)
+#define PL_OUT2(k,v) freezer.put (KW_ ## k, v)
+
+ PL_OUT (password);
+ PL_OUT2 (title, own_title);
+ PL_OUT (gender);
+ PL_OUT (gen_hp);
+ PL_OUT (gen_sp);
+ PL_OUT (gen_grace);
+ PL_OUT (listening);
+ PL_OUT (bowtype);
+ PL_OUT (petmode);
+ PL_OUT (peaceful);
+ PL_OUT (digestion);
+ PL_OUT2 (pickup, mode);
+ PL_OUT (outputs_sync);
+ PL_OUT (outputs_count);
+
+ freezer.put (KW_usekeys, usekeys == key_inventory ? "key_inventory" : (usekeys == keyrings ? "keyrings" : "containers"));
+ freezer.put (KW_unapply, unapply == unapply_nochoice ? "unapply_nochoice" : (unapply == unapply_never ? "unapply_never" : "unapply_always"));
+
+ PL_OUT2 (map, maplevel);
+ PL_OUT (savebed_map);
+ PL_OUT (bed_x);
+ PL_OUT (bed_y);
+ PL_OUT (weapon_sp);
+ PL_OUT (weapon_sp_left);
+ PL_OUT2 (Str, orig_stats.Str);
+ PL_OUT2 (Dex, orig_stats.Dex);
+ PL_OUT2 (Con, orig_stats.Con);
+ PL_OUT2 (Int, orig_stats.Int);
+ PL_OUT2 (Pow, orig_stats.Pow);
+ PL_OUT2 (Wis, orig_stats.Wis);
+ PL_OUT2 (Cha, orig_stats.Cha);
+
+ PL_OUT2 (lev_array, 10);
+
+ for (int i = 1; i <= 10; i++)
+ {
+ freezer.add (levhp [i]); freezer.add ('\n');
+ freezer.add (levsp [i]); freezer.add ('\n');
+ freezer.add (levgrace[i]); freezer.add ('\n');
+ }
+
+ freezer.put (ob->contr);
+ freezer.put (KW_endplst);
+
+ SET_FLAG (ob, FLAG_NO_FIX_PLAYER);
+ CLEAR_FLAG (ob, FLAG_WIZ);
+ ob->write (freezer);
+
+ CLEAR_FLAG (ob, FLAG_NO_FIX_PLAYER);
+
+ /* Eneq(@csd.uu.se): Reveal the container if we have one. */
+ ob->container = container;
+
+ ob->flag [FLAG_WIZ] = wiz;
+
+ INVOKE_PLAYER (SAVE_DONE, ob->contr);
+
+ return true;
+}
+
+bool
+player::save_pl (const char *path)
+{
+ object_freezer freezer;
+
+ if (!save_pl (freezer))
+ return false;
+
+ return freezer.save (path);
+}
+
+player *
+player::load_pl (object_thawer &f)
+{
+ int maxerrs = 20;
+
+ player *pl = new player;
+
+ pl->savebed_map = first_map_path;
+
+ /* Loop through the file, loading the rest of the values */
+ for (;;)
+ {
+ switch (f.kw)
+ {
+ case KW_EOF:
+ LOG (llevError, "%s: unexpected EOF while reading player header\n", f.name);
+ goto failure;
+
+ default:
+ LOG (llevError, "%s: skipping unknown key in player header: %s\n", f.name, f.kw_str);
+ if (!--maxerrs) goto failure;
+ break;
+
+ case KW_ERROR:
+ LOG (llevError, "%s: parse error while reading player header, skipping (%s,%s).\n", f.name, f.kw_str, f.value);
+ if (!--maxerrs) goto failure;
+ break;
+
+ case KW_endplst:
+ f.next ();
+
+ if (object *op = pl->ob->read (f))
+ pl->set_object (op);
+ else
+ goto failure;
+
+ INVOKE_PLAYER (LOAD, pl);
+
+ return pl;
+
+ case KW_oid: f.get (pl, f.get_sint32 ()); break;
+ case KW_password: assign (pl->password , f.get_str ()); break;
+ case KW_title: assign (pl->own_title, f.get_str ()); break;
+ case KW_bowtype: pl->bowtype = (bowtype_t) f.get_sint32 (); break;
+ case KW_petmode: pl->petmode = (petmode_t) f.get_sint32 (); break;
+ case KW_gender: f.get (pl->gender); break;
+ case KW_listening: f.get (pl->listening); break;
+ case KW_peaceful: f.get (pl->peaceful); break;
+ case KW_digestion: f.get (pl->digestion); break;
+ case KW_pickup: f.get (pl->mode); break;
+ case KW_outputs_sync: f.get (pl->outputs_sync); break;
+ case KW_outputs_count: f.get (pl->outputs_count); break;
+ case KW_map: f.get (pl->maplevel); break;
+ case KW_savebed_map: f.get (pl->savebed_map); break;
+ case KW_bed_x: f.get (pl->bed_x); break;
+ case KW_bed_y: f.get (pl->bed_y); break;
+ case KW_weapon_sp: f.get (pl->weapon_sp); break;
+ case KW_weapon_sp_left:f.get (pl->weapon_sp_left); break;
+ case KW_Str: f.get (pl->orig_stats.Str); break;
+ case KW_Dex: f.get (pl->orig_stats.Dex); break;
+ case KW_Con: f.get (pl->orig_stats.Con); break;
+ case KW_Int: f.get (pl->orig_stats.Int); break;
+ case KW_Pow: f.get (pl->orig_stats.Pow); break;
+ case KW_Wis: f.get (pl->orig_stats.Wis); break;
+ case KW_Cha: f.get (pl->orig_stats.Cha); break;
+ case KW_gen_hp: f.get (pl->gen_hp); break;
+ case KW_gen_sp: f.get (pl->gen_sp); break;
+ case KW_gen_grace: f.get (pl->gen_grace); break;
+
+ case KW_usekeys:
+ if (!strcmp (f.get_str (), "key_inventory"))
+ pl->usekeys = key_inventory;
+ else if (!strcmp (f.get_str (), "keyrings"))
+ pl->usekeys = keyrings;
+ else if (!strcmp (f.get_str (), "containers"))
+ pl->usekeys = containers;
+ else
+ LOG (llevDebug, "load_player: got unknown usekeys type: %s\n", f.get_str ());
+ break;
+
+ case KW_unapply:
+ if (!strcmp (f.get_str (), "unapply_nochoice"))
+ pl->unapply = unapply_nochoice;
+ else if (!strcmp (f.get_str (), "unapply_never"))
+ pl->unapply = unapply_never;
+ else if (!strcmp (f.get_str (), "unapply_always"))
+ pl->unapply = unapply_always;
+ else
+ LOG (llevDebug, "load_player: got unknown unapply type: %s\n", f.get_str ());
+ break;
+
+ case KW_lev_array:
+ {
+ int count = f.get_sint32 ();
+
+ for (int i = 1; i <= count; i++)
+ {
+ char line [32];
+
+ fgets (line, 32, f); pl->levhp [i] = atoi (line);
+ fgets (line, 32, f); pl->levsp [i] = atoi (line);
+ fgets (line, 32, f); pl->levgrace[i] = atoi (line);
+ }
+ }
+ break;
+ }
+
+ f.next ();
+ }
+
+failure:
+ LOG (llevError, "%s: too many or too grave errors, aborting player load.\n", f.name);
+
+ if (pl->ob)
+ pl->ob->destroy ();
+
+ pl->destroy ();
+
return 0;
}
+